Files
python/TangDou/AcWing/RongChi/HDU4407.cpp
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

91 lines
3.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl "\n"
const int N = 400010;
unordered_map<int, int> mp; // 能用Hash表不用红黑树
vector<int> p; // 将m拆分成的质数因子序列p
/*
等差数列求和=(首项+末项)*项数/2
本题中:首项=t,项数=n,公差=t
举栗子:3,6,9 是一个等差数列,公差=3
我们可以这样看(1,2,3)*3,也就是先计算(1,2,3)的和,再乘以3=(1+3)*3/2*3=18
*/
int get(int t, int n) {
return n * (n + 1) / 2 * t;
}
// 容斥原理+等差数列加法和
// 求解[1,n]中与c互素的所有数字的和
// = [1,n]的数字总和 - [1,n]中所有与c存在公共因子的数的和
int calc(int n) {
int sum = get(1, n); // [1,n]的数字总和
int s = 0;
for (int i = 1; i < (1 << p.size()); i++) {
int cnt = 0, t = 1;
for (int j = 0; j < p.size(); j++) {
if (i >> j & 1) {
cnt++;
t *= p[j];
}
}
if (cnt & 1)
s += get(t, n / t);
else
s -= get(t, n / t);
}
return sum - s; // 总数,减去不互质的,等于,互质的数字加法和
}
signed main() {
#ifndef ONLINE_JUDGE
freopen("HDU4407.in", "r", stdin);
#endif
// 加快读入
ios::sync_with_stdio(false), cin.tie(0);
int T; // T组测试数据
cin >> T;
while (T--) {
mp.clear(); // 注意此处,每次测试案例都要清零
int n, m;
cin >> n >> m; // 1~n ,共n 个长度的序列
while (m--) { // m个询问
int choice;
cin >> choice; // 操作
int x, y, P;
if (choice == 1) { // 查询[x,y]内与c互素的数的和
cin >> x >> y >> P;
p.clear(); /// 初始化
// 分解质因数
int t = P; // 复制出来
for (int i = 2; i * i <= t; i++) {
if (t % i == 0) {
p.push_back(i);
while (t % i == 0) t = t / i;
}
}
if (t > 1) p.push_back(t);
int sum = calc(y) - calc(x - 1); // 类似于前缀和求[x~y]区间内的等差数列加法和
// 遍历已经录入的所有修改
for (auto it = mp.begin(); it != mp.end(); it++) {
int a = it->first, b = it->second;
// 如果修改的不存本次查询的范围内,改了也不影响我,没用,不理
if (a > y || a < x) continue;
// 本来互素,结果被你改了,那就需要减掉这个数值
if (__gcd(a, P) == 1) sum -= a;
// 修改后互素的要加上新数值
if (__gcd(b, P) == 1) sum += b;
}
cout << sum << endl;
} else {
cin >> x >> P;
mp[x] = P; // 修改序列内容
}
}
}
}