莫比乌斯的模板题
都是差不多的
F(m)为gcd(i,j) = m(i∈[1,m],j∈[1,n])的个数
f(m) = ∑(md) F(d) 意义为gcd(i,j)为m的倍数的个数
运用莫比乌斯反演得到
F(m) = ∑(md)μ(d/m) * f(d)
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; #define MOD 10007 const int ListSize = 10005; int PrimeSize,n; int isPrime[ListSize],Mu[ListSize],Prime[ListSize]; int total[ListSize],f[ListSize],a[ListSize]; void Init(){ Mu[1] = 1; memset(isPrime,1,sizeof(isPrime)); for (int i=2;i<=ListSize;i++){ if (isPrime[i]){ PrimeSize ++; Prime[PrimeSize] = i; Mu[i] = -1; } for (int j=1;j<=PrimeSize && Prime[j] * i<= ListSize;j++){ isPrime[i*Prime[j]] = 0; if (i % Prime[j] == 0){ Mu[i*Prime[j]] = 0; break; } else { Mu[i*Prime[j]] = -Mu[i]; } } } } int main(){ // freopen("test.in","r",stdin); Init(); while (cin >> n){ int maxn = 0; memset(total,0,sizeof(total)); memset(f,0,sizeof(f)); for (int i=0;i<n;i++){ scanf("%d",&a[i]); total[a[i]] ++; maxn = max(maxn,a[i]); } for (int i=1;i<=maxn;i++){ for (int j=i;j<=maxn;j+=i){ f[i] += total[j]; } } LL ans = 0,temp; for (int i=1;i<=maxn;i++){ temp = 0; for (int j=i;j<=maxn;j+=i){ temp = (temp + Mu[j/i] * f[j] * f[j] % MOD) % MOD; } ans = (ans + temp * 1ll * i % MOD * (i-1) % MOD) % MOD; } cout << ans << endl; } }
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; const int ListSize = 100005; int PrimeSize; int isPrime[ListSize],Mu[ListSize],Prime[ListSize]; int Sum[ListSize]; int a,b,c,d,k,T; void Init(){ Mu[1] = 1; Sum[0] = 0; memset(isPrime,1,sizeof(isPrime)); for (int i=2;i<=ListSize;i++){ if (isPrime[i]){ PrimeSize ++; Prime[PrimeSize] = i; Mu[i] = -1; } for (int j=1;j<=PrimeSize && Prime[j] * i<= ListSize;j++){ isPrime[i*Prime[j]] = 0; if (i % Prime[j] == 0){ Mu[i*Prime[j]] = 0; break; } else { Mu[i*Prime[j]] = -Mu[i]; } } } for (int i=1;i<ListSize;i++){ Sum[i] = Sum[i-1] + Mu[i]; } } int main(){ // freopen("test.in","r",stdin); Init(); cin >> T; for (int times = 1; times <= T; times ++){ cin >> a >> b >> c >> d >> k; cout << "Case " << times << ": "; if (k == 0){ cout << "0" << endl; continue; } b = b / k; d = d / k; if (b > d){ swap(b,d); } LL ans1 = 0; int last; for (int i=1;i<=b;i=last+1){ last = min(b/(b/i),d/(d/i)); ans1 += (LL)(Sum[last] - Sum[i-1]) * (b/i) * (d/i); } LL ans2 = 0; for (int i=1;i<=b;i=last+1){ last = b/(b/i); ans2 += (LL) (Sum[last] - Sum[i-1]) * (b/i) * (b/i); } LL ans = ans1 - ans2 / 2; cout << ans << endl; } }