首页 > 代码库 > HDU 1695 (莫比乌斯反演) GCD
HDU 1695 (莫比乌斯反演) GCD
题意:
从区间[1, b]和[1, d]中分别选一个x, y,使得gcd(x, y) = k, 求满足条件的xy的对数(不区分xy的顺序)
分析:
虽然之前写过一个莫比乌斯反演的总结,可遇到这道题还是不知道怎么应用。
这里有关于莫比乌斯反演的知识,而且最后的例题中就有这道题并给出了公式的推导。
1 #include <cstdio> 2 #include <algorithm> 3 typedef long long LL; 4 5 const int maxn = 1000000; 6 int mu[maxn + 10], vis[maxn + 10], prime[maxn], cnt; 7 8 void Mobius() 9 {10 mu[1] = 1;11 cnt = 0;12 for(int i = 2; i <= maxn; ++i)13 {14 if(!vis[i])15 {16 mu[i] = -1;17 prime[cnt++] = i;18 }19 for(int j = 0; j < cnt && i*prime[j] <= maxn; ++j)20 {21 vis[i*prime[j]] = 1;22 if(i % prime[j] != 0) mu[i*prime[j]] = -mu[i];23 else24 {25 mu[i*prime[j]] = 0;26 break;27 }28 }29 }30 }31 32 int main()33 {34 //freopen("1695in.txt", "r", stdin);35 36 Mobius();37 int T;38 scanf("%d", &T);39 for(int kase = 1; kase <= T; ++kase)40 {41 int a, b, c, d, k;42 scanf("%d%d%d%d%d", &a, &b, &c, &d, &k);43 44 if(k == 0)45 {46 printf("Case %d: 0\n", kase);47 continue;48 }49 50 b /= k, d /= k;51 if(b > d) std::swap(b, d);52 LL hehe = 0, haha = 0;53 for(int i = 1; i <= b; ++i)54 hehe += (LL)mu[i] * (b/i) * (d/i);55 for(int i = 1; i <= b; ++i)56 haha += (LL)mu[i] * (b/i) * (b/i); //因为题目不区分xy的顺序,所以要减去重复的部分57 LL ans = hehe - haha/2;58 59 printf("Case %d: %I64d\n", kase, ans);60 }61 62 return 0;63 }
HDU 1695 (莫比乌斯反演) GCD
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。