BZOJ 1101 [POI2007]Zap | 第一道莫比乌斯反(繁)演(衍)
题目:
http://www.lydsy.com/JudgeOnline/problem.php?id=1101
题解:
http://www.cnblogs.com/mrha/p/8203612.html
数学公式太难打了,核心思想是化成gcd(i,j)==1,然后用莫比乌斯反演变成枚举约数d,然后再搞式子
#include<cstdio> #include<algorithm> #define N 50005 typedef long long ll; using namespace std; int T,a,b,d,mu[N],prime[N],tot,sum[N]; bool notprime[N]; ll ans; void getmu() { mu[1] = sum[1] = 1; for(int i = 2; i <= N; i++){ if(!notprime[i]) mu[i] = -1, prime[++tot] = i; for(int j = 1; j <= tot && i * prime[j] <= N; j++){ notprime[i * prime[j]] = 1; if(i % prime[j]) mu[i * prime[j]] = -mu[i]; else{ mu[i * prime[j]] = 0; break; } } sum[i] = sum[i - 1] + mu[i]; } } int main() { getmu(); scanf("%d",&T); while (T--) { scanf("%d%d%d",&a,&b,&d),a/=d,b/=d,ans=0; if (a>b) swap(a,b); for (int i=1,last=0;i<=a;i=last+1) { last=min(a/(a/i),b/(b/i)); ans+=ll(a/i)*(b/i)*(sum[last]-sum[i-1]); } printf("%lld\n",ans); } return 0; }