hdu6053-容斥+莫比乌斯函数+优化
来源:互联网 发布:乐视软件商城 编辑:程序博客网 时间:2024/05/29 17:01
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6053
题意:给一个序列A,要求构造序列B,使得 Bi <= Ai, gcd(Bi) > 1, 1 <= i <= n, 输出构造的方法数取模1e9+7
思路:
求出序列A的最大值Max,最小值Min
枚举整个序列的{d| 2 <= d <= Min}, 对于每个d来说,每个Bi可以构造的数为d, 2*d, ..., (Ai/d)*d,
所以每个d对最后结果的贡献值为 π(Ai/d), 如果不考虑重复,答案为Σd*π(Ai/d),但是最后会有重复,
例如d = 2时, 3*d = 6, d = 3时, 2*d = 6, d = 6时, 1*d = 6,这样6这个构造方案就重复了,需要减去,
而直接减去d=6时的方案,会导致减多了,需要加上多减的一部分,到这里其实就是容斥了...
对d进行质因数分解,d = a1^p1 * a2^p2 * ... * am^pm,若存在pi>1,则此时的方案数忽略掉,不加也不减,
若m为奇数,即d由奇数个质因数组成,则此时的方案数要加上,若m为偶数,则此时的方案数要减去,
这和莫比乌斯函数的定义正好相反,所以可以预处理出莫比乌斯函数,这样统计以后最后的结果就是要求的答案。
所以就是求Σd * -mobius(d) * π(Ai/d),但是现在复杂度是o(n^2),所以要进行优化
考虑到π(Ai/d)中可能会有很多重复的数(例如,d = 5 时, Ai = 5, 6, 7, 8, 9时 Ai/d是相等的),可以想办法将相同的数的个数统计出来,
然后使用快速幂计算多个数的乘积降低复杂度。所以从枚举最大公约数改为枚举 最大公约数的倍数 的个数, 即Ai/d,
下限和上限分别为,1和max(A)/d, 求Σd * -mobius(d) * π(t^f(t,d)), t = Ai/d, f(t,d)为t的个数, n + n/2 + n/3 + ... + n / n = n * (1 + 1/2 + 1/3 + ... + 1/n) ≈ n*log(n),再乘上快速幂的复杂度,总的复杂度为n * (log(n)) ^ 2.
计算f(t,d)时,可以将数组每个数Ai的个数统计出来,然后求前缀和,记为cnt[Ai],对于每个d和t,f(d,t) = cnt[d * t + d - 1] - cnt[d * t - 1].
代码:
# include <iostream># include <algorithm># include <cstdio># include <cstring>using namespace std;typedef long long ll;const int maxn = 1e5 + 5;const int mod = 1e9 + 7;int vis[maxn];int pri[maxn];int mu[maxn];int a[maxn];int cnt[maxn * 2];int n;int len;void init() { memset(vis, 0, sizeof vis); mu[1] = 1; len = 0; for (int i = 2; i < maxn; ++i) { if (!vis[i]) { pri[len++] = i; mu[i] = -1; } for (int j = 0; j < len && i * pri[j] < maxn; ++j) { vis[i * pri[j]] = 1; if (i % pri[j]) mu[i * pri[j]] = -mu[i]; else { mu[i * pri[j]] = 0; break; } } }}int fast_pow(int x, int n) { int r = 1; while (n) { if (n & 1) r = (ll)r * x % mod; x = (ll)x * x % mod; n >>= 1; } return r;}int main(void){ init(); int T, Case = 0; scanf("%d", &T); while (T-- && scanf("%d", &n)) { memset(cnt, 0, sizeof cnt); int Min = 1e5 + 1, Max = -1; for (int i = 0; i < n; ++i) { scanf("%d", a + i); ++cnt[a[i]]; Min = min(Min, a[i]); Max = max(Max, a[i]); } for (int i = Min; i <= Max * 2; ++i) cnt[i] += cnt[i - 1]; int ans = 0; for (int d = 2; d <= Min; ++d) { int tmp = 1; for (int i = 1; i <= Max / d; ++i) { tmp = (ll)tmp * fast_pow(i, cnt[i * d + d - 1] - cnt[i * d - 1]) % mod; } ans = ((ll)ans - mu[d] * tmp + mod) % mod; } printf("Case #%d: %d\n", ++Case, ans); } return 0;}
- hdu6053-容斥+莫比乌斯函数+优化
- HDU6053(莫比乌斯函数+容斥定理)
- hdu6053 TrickGCD 莫比乌斯函数 容斥原理
- HDU6053-TrickGCD 容斥原理+莫比乌斯反演
- hdu6053 莫比乌斯函数
- 莫比乌斯函数 hdu6053
- HDU6053(莫比乌斯)
- hdu6053 TrickGCD 莫比乌斯反演
- hdu6053-莫比乌斯反演
- 【数论】莫比乌斯反演证明+HDU6053(莫比乌斯函数)
- [莫比乌斯函数][分段] hdu6053 TrickGCD (2017 Multi-University Training Contest
- hdu6053 多校第二场(莫比乌斯函数,枚举)
- 【2017多校】HDU6053 TrickGCD 【莫比乌斯】
- codeforces803F Coprime Subsequences -- 莫比乌斯函数+容斥
- hdu 6053 莫比乌斯函数(容斥)
- TrickGCD(莫比乌斯函数,容斥)
- HDU6053 TrickGCD(容斥原理)
- HDU6053 前缀和+容斥
- 剑指offer——25.复杂链表的复制
- nyoj 44子串和
- 好好理解一下CMS收集器
- asp.net mvc post请求断点调试
- MFC动态创建可停靠窗口,窗口添加控件并读写控件中的数据
- hdu6053-容斥+莫比乌斯函数+优化
- 操作线程的方法
- spark 之 Phoenix详解
- mysql 获取当前日期前一天
- python 日期API
- [3-02]大型网站及其架构演进过程
- Validate Binary Search Tree
- 安装slowhttptest各种问题解决方案
- 微信js-sdk分享详解及demo实例