题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1695
莫比乌斯反演参考资料:http://www.cnblogs.com/chenyang920/p/4811995.html
https://baike.baidu.com/item/%E8%8E%AB%E6%AF%94%E4%B9%8C%E6%96%AF%E5%8F%8D%E6%BC%94
我们现在就是求f(1),即x为1,所以就是所有的d都满足,即枚举所有的d~(1-b),注意减去重复的部分。
#include <bits/stdc++.h> using namespace std; const int MAXN = 1000000; bool check[MAXN+10]; int prime[MAXN+10]; int mu[MAXN+10]; void Moblus() { memset(check,false,sizeof(check)); mu[1] = 1; int tot = 0; for(int i = 2; i <= MAXN; i++) { if( !check[i] ) { prime[tot++] = i; mu[i] = -1; } for(int j = 0; j < tot; j++) { if(i * prime[j] > MAXN) break; check[i * prime[j]] = true; if( i % prime[j] == 0) { mu[i * prime[j]] = 0; break; } else { mu[i * prime[j]] = -mu[i]; } } } } int main() { //freopen("in.txt","r",stdin); int T; int a,b,c,d,k; Moblus(); scanf("%d",&T); int iCase = 0; while(T--) { iCase++; scanf("%d%d%d%d%d",&a,&b,&c,&d,&k); if(k == 0) { printf("Case %d: 0\n",iCase); continue; } b /= k; d /= k; if(b > d) swap(b,d); long long ans1 = 0; for(int i = 1; i <= b; i++) ans1 += (long long)mu[i]*(b/i)*(d/i); long long ans2 = 0; for(int i = 1; i <= b; i++) ans2 += (long long)mu[i]*(b/i)*(b/i); ans1 -= ans2/2; printf("Case %d: %I64d\n",iCase,ans1); } return 0; }
然后就是可以用分块优化了
时间: 2024-12-28 02:34:53