HDU-4407 Sum 容斥定理
对于一个数F,设F = p1^e1*p2^e2...*pn^en 那么[1-N]内与其互质的数和与D = p1*p2*...pn是一致的,因为和F、D互质的数都是不含有他们的素因子的数。对于D这个数求[1-N]内有多少个与其互质的数就可用运用容斥定理来求解了。以6为例,首先计算出与2不互质的数,用等差数列公式能够计算出这些满足于2不互质数的和,接着就加上与3不互质的和,最后再减一次与6不互质的和即可。对于那些改变的数,由于数量不是很多,可以单独拿出来进行处理。
代码如下:
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<queue> #include<set> #include<map> #include<cstring> #include<vector> #include<string> #define MAXN 800 #define LL long long using namespace std; int N, M, rec[50]; map<int,int>mp; bool p[805]; int pri[805], idx; inline int gcd(int a, int b) { return b ? gcd(b, a % b) : a; } inline void Getprime() { idx = -1; for (int i = 2; i <= MAXN; ++i) { if (!p[i]) { pri[++idx] = i; } for (int j = 0; i * pri[j] <= MAXN; ++j) { p[i*pri[j]] = 1; if (i % pri[j] == 0) break; } } } inline long long cal(int num, int x) { if (x == 0) return 0; long long ret = 0; int cnt = 0, mask; int LIM = (int)sqrt(double(num)); for (int i = 0; pri[i] <= LIM; ++i) { if (num % pri[i] == 0) { rec[++cnt] = pri[i]; while (num % pri[i] == 0) { num /= pri[i]; } } if (num == 1) break; } if (num != 1) { rec[++cnt] = num; } mask = 1 << cnt; for (int i = 1; i < mask; ++i) { int tsum = 0; long long yinzi = 1; for (int j = 0; j < cnt; ++j) { if (i & (1 << j)) { ++tsum; yinzi *= rec[j+1]; } } if (tsum & 1) { long long k = x / yinzi; ret += ((yinzi + k * yinzi) * k) >> 1; } else { int k = x / yinzi; ret -= ((yinzi + k * yinzi) * k) >> 1; } } return ret; } inline long long SUM(int x) { return ((1 + 1LL * x) * 1LL * x) >> 1; } int main() { Getprime(); int T, op, a, b, p; map<int,int>::iterator it; long long ret; scanf("%d", &T); while (T--) { mp.clear(); scanf("%d %d", &N, &M); for (int i = 1; i <= M; ++i) { scanf("%d", &op); if (op == 1) { ret = 0; scanf("%d %d %d", &a, &b, &p); for (it = mp.begin(); it != mp.end(); ++it) { if (it->first != it->second && it->first >= a && it->first <= b) { ret -= gcd(it->first, p) == 1 ? it->first : 0; ret += gcd(it->second, p) == 1 ? it->second : 0; } } ret += SUM(b) - SUM(a-1) - (cal(p, b) - cal(p, a-1)); printf("%I64d\n", ret); } else { scanf("%d %d", &a, &b); mp[a] = b; } } } return 0; }