【BZOJ】2005 [Noi2010]能量采集
2016-07-19 19:54
375 查看
[Noi2010]能量采集
题目链接
[Noi2010]能量采集题目大意
中文题,题目意思很清楚,这里就不说了,总之就是要你求这个:ans=∑x=1n∑y=1m[2(gcd(x,y)−1)+1]
题解
莫比乌斯反演 化简
可以化简:ans=2∑x=1n∑y=1mgcd(x,y)−nm
可以看到现在的首要任务是求前面的和式,考虑到gcd(x,y)只有有限个值,我们设
f(d):gcd(x,y)=d的(x,y)的对数
当然x和y都在范围内。
这样的话我们的ans可以改写为:
ans=2∑dd⋅f(d)−nm
看到首要任务是求f(d),这里我们用莫比乌斯反演,于是我们又设:
F(d):d|gcd(x,y)的(x,y)的对数
又因为:
F(d)=nd⋅md
根据反演公式,有:
f(x)=∑x|dμ(dx)⋅nd⋅md
到这里基本又是一些老东西了,令T=xd什么的,最后可以化简到:
f(x)=∑TnTmT∑x|Tμ(Tx)
把x换成d,再带入ans,得到:
ans=∑TnTmT∑d|Td⋅μ(Tx)
到这里,我们的μ(x)函数有一个性质:
∑d|nd⋅μ(nd)=ϕ(n)
这个可以用用欧拉函数的性质∑d|nϕ(d)=n这个式子莫比乌斯反演得来,所以我们可以把ans变为
ans=∑TnTmT⋅ϕ(T)
可以看到最后的式子非常简单,先筛出phi(d)然后分块求和即可。
代码
不能用%I64d,会WA#include <iostream> #include <cstring> #include <cstdio> #define LL long long #define maxn 100005 using namespace std; LL n,m,p[maxn-5],cnt,phi[maxn]; bool vis[maxn-5]; void setup(int high) { cnt=0; memset(p,0,sizeof(p)); memset(vis,0,sizeof(vis)); memset(phi,0,sizeof(phi)); phi[1]=1; for (int i=2;i<=high;i++) { if (!vis[i]) { vis[i]=1; p[cnt++]=i; phi[i]=i-1; } for (int j=0;j<cnt && i*p[j]<=high;j++) { vis[i*p[j]]=1; if (i%p[j]) phi[i*p[j]]=phi[i]*(p[j]-1); else { phi[i*p[j]]=phi[i]*p[j]; break; } } } for (int i=1;i<=high;i++) phi[i]+=phi[i-1]; } int main() { scanf("%lld%lld",&n,&m); setup(min(n,m)); LL last=0,t=min(n,m); LL ans=0; for (int i=1;i<=t;i=last+1) { last=min(n/(n/i),m/(m/i)); ans+=(LL) (n/i)*(m/i)*(phi[last]-phi[i-1]); } ans=(LL)ans*2-n*m; printf("%lld\n",ans); return 0; }
相关文章推荐
- socket通讯,客户端获取数据丢失问题
- sed命令
- 喷水装置-(二)
- ajax小结
- 7.2 大整数四则运算
- Nosql 背景
- 331. Verify Preorder Serialization of a Binary Tree
- HDU1671 字典树
- 深入浅出spring IOC中三种依赖注入方式
- Android取消EditText自动获取焦点默认行为
- HDU 2546 饭卡
- Spring——IOC/DI理解
- Android Studio IDE的 LogCat如何过滤指定应用的调试信息
- 如何在VMware8虚拟机里安装Xp GHOST系统 解决不能启动Xp系统方法
- POJ 2533 Longest Ordered Subsequence
- hdu 1495 非常可乐
- 如何烧写Bubblegum-96 board
- 面试题42:翻转单词顺序
- UVA 10970-Big Chocolate
- 2016 Multi-University Training Contest 1