【HDU6134】Battlestation Operational (莫比乌斯反演)
来源:互联网 发布:mac终端返回上级目录 编辑:程序博客网 时间:2024/06/01 09:31
多校第八场没想到碰到了一直想学却没有学的莫比乌斯反演,比赛时不出意外的打出了gg,便下定决心要好好会一会高深的莫比乌斯反演(在菜鸡的眼里是这样),下面是我的一些学习资料:
http://www.cnblogs.com/chenyang920/p/4811995.html
http://blog.csdn.net/acdreamers/article/details/8542292
https://wenku.baidu.com/view/fbec9c63ba1aa8114431d9ac.html
看完这些之后不得不佩服这些数学家的伟大,这个算法对于解决组合问题,包含gcd的条件的问题实在太厉害了。
然后就要开始讲这道题目了,这场的多校赛题目都是巨长,我就大概说一下这道题的题意:
题目给出一个n*n的矩阵对于矩阵中每一个点(x, y) 如果x >= y && gcd(x, y) = 1, 那么这个点的值为 x / y 向上取整, 否则就为0,要求这个矩阵的各个点的值的总和。即如公式所见:
分析:
首先设
因为gcd(i, j)等于1才有效,因此i / j 一定无法整除(除了j = 1),且结果就为 i / j + 1,因此有如下转化,其中φ(i)为欧拉函数
然后就是重要发现:
然后运用莫比乌斯反演
可得:
继续转化:
其中τ(n)表示n的约数个数,是积性函数也可以线性求出
其实后来发现:
F(n) = F(n - 1) + d(n - 1) + 1, 其中d(n)表示n的约数的个数
这样可以递推出每一项的F(n),
然后利用莫比乌斯反演公式就可以求出每一项f(n),注意这里求每一项的f(n)可以枚举j, 然后j的倍数的答案可以很容易求出,因为调和级数这样复杂度为nlog(n), f(n)的前缀和就是答案
#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <map>#include <set>#include <vector>#include <queue>#include <cmath>#include <bitset>using namespace std;const int M = 1e9 + 7;const int MAXN = 1000005;int g[MAXN], pre[MAXN];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 <= 1000000; 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 factor[100][2];int getFactors(int x){ int fatCnt = 0; int tmp = x; for(int i = 0; prime[i] <= tmp / prime[i];i++) { factor[fatCnt][1] = 0; if(tmp%prime[i] == 0) { factor[fatCnt][0] = prime[i]; while(tmp%prime[i] == 0) { factor[fatCnt][1]++; tmp /= prime[i]; } fatCnt++; } } if(tmp != 1) { factor[fatCnt][0] = tmp; factor[fatCnt++][1] = 1; } return fatCnt;}int main(){ Moblus(); g[1] = 1; int cnt = 1; for(int i = 2; i <= 1000000; ++i) { g[i] = g[i - 1] + cnt + 1; int m = getFactors(i); cnt = 1; for(int j = 0; j < m; ++j) cnt *= (factor[j][1] + 1); } for(int j = 1; j <= 1000000; ++j) for(int k = j, t = 1; k <= 1000000; k += j, t++) pre[k] += mu[t] * g[j]; for(int i = 2; i <= 1000000; ++i) pre[i] = (pre[i] + pre[i - 1]) % M; int n; while(scanf("%d", &n) != EOF) { printf("%d\n", pre[n]); } return 0;}
然后这里还附一份我觉得更简洁的代码:
#include<cstdio>#include<cstring>#include<vector>using namespace std;typedef long long int ll;const ll mod = 1e9 + 7;const int A = 1e6 + 10;int mu[A],pri[A],tot;ll d[A],cnt[A],sum[A];bool vis[A];void init(){ tot = 0;mu[1] = d[1] = 1; for(int i=2 ;i<A ;i++){ if(!vis[i]){mu[i] = -1;pri[++tot] = i;d[i] = 2;cnt[i] = 1;} for(int j=1 ;j<=tot && pri[j]*i<A ;j++){ vis[i*pri[j]] = 1; if(i%pri[j] == 0){ d[i*pri[j]] = d[i]/(cnt[i]+1)*(cnt[i]+2); cnt[i*pri[j]] = cnt[i] + 1; mu[i*pri[j]] = 0; break; } d[i*pri[j]] = d[i]<<1; cnt[i*pri[j]] = 1; mu[i*pri[j]] = -mu[i]; } } sum[1] = 1; for(int i=2 ;i<A ;i++){ sum[i] = (sum[i-1] + d[i-1] + 1)%mod; } for(int i=1 ;i<A ;i++){ sum[i] = (sum[i] + sum[i-1])%mod; mu[i] = (mu[i] + mu[i-1])%mod; }}int main(){ init(); int n; while(~scanf("%d",&n)){ ll ans = 0; int last; for(int i=1 ;i<=n ;i=last + 1){ last = n/(n/i); ans = (ans + (mu[last]-mu[i-1])%mod*(sum[n/i])%mod)%mod; } ans = (ans%mod + mod)%mod; printf("%I64d\n",ans); } return 0;}
- 【HDU6134】Battlestation Operational (莫比乌斯反演)
- 【HDU6134】Battlestation Operational(莫比乌斯反演)
- hdu6134 Battlestation Operational 莫比乌斯反演
- Battlestation Operational(hdu6134 莫比乌斯反演)
- HDU6134 Battlestation Operational 【莫比乌斯】
- hdu 6134 Battlestation Operational 莫比乌斯反演
- 解题报告:HDU_6134:Battlestation Operational (莫比乌斯反演)
- HDU 6134 Battlestation Operational(积性函数+莫比乌斯反演)
- hdu 6134 Battlestation Operational (莫比乌斯反演+线性筛法+差分)
- HDU 6134 Battlestation Operational(莫比乌斯反演+线性筛)
- HDU 6134 Battlestation Operational 莫比乌斯反演 + 数学推导
- HDU 6134(2017 多校训练:Battlestation Operational(莫比乌斯反演))
- HDU 6134 Battlestation Operational 2017多校8 莫比乌斯反演
- hdu6134-(莫比乌斯反演)
- HDU6134(莫比乌斯反演)
- hdu6134-莫比乌斯反演+思维
- HDU 6134 && 2017 多校训练:Battlestation Operational(莫比乌斯反演+积性函数)
- HDU 6134 Battlestation Operational(基本数论+莫比乌斯反演)——2017 Multi-University Training Contest
- 51Nod 1265:四点共面(计算几何)
- 文章标题
- JavaWeb中点赞功能的实现及完整实例
- jsp倒计时循环调用
- tomcat热部署配置
- 【HDU6134】Battlestation Operational (莫比乌斯反演)
- gcc: error trying to exec 'as': execvp: No such file or directory
- 已有 JFFs2文件系统的修改
- C# 自定义cookie封装类,简化Cookie操作
- 【新mac工作机】docker化部署jenkins环境(一)
- HDU6136Death Podracing
- Muiltset和MultiMap学习--如何让map存放相同的key
- React ES5与ES6语法写法比较
- [日推荐] 『无忧育儿说』养育孩子就是这么简单!