[bzoj2005][Noi2010]能量采集
2016-06-16 19:55
381 查看
Description
在平面直角坐标系中,点(x,y)的代价定义为它和原点的连线中经过多少的其他整点个数*2+1。求横坐标在1~n且纵坐标在1~m的所有点的代价和。n,m<=10^5
Solution
首先,一个点的代价就是gcd(x,y)*2-1(蒟蒻不会证,各路大犇们带带我呗)然后,我们就变成了要求∑i=1n∑j=1mgcd(i,j)了。
很经典的莫比乌斯反演。
首先,设f(d)表示有多少个gcd(i,j)=d,g(d)表示有多少个gcd(i,j)是d的倍数。
那么很明显,g(d)=⌊nd⌋∗⌊md⌋
则根据反演得f(d)=∑i=1⌊nd⌋μ(i)g(di)
即f(d)=∑i=1⌊nd⌋μ(i)⌊ndi⌋∗⌊mdi⌋
那么Ans=∑d=1nd∑i=1⌊nd⌋μ(i)⌊ndi⌋∗⌊mdi⌋
第一个∑和第二个∑各分一次块就好了。(分块大法好)
当然,我们也可以预处理出后面的东西,或者先变形一下再预处理,然后就能分块根号n(似乎没卵用)
Code
#include<cstdio> #include<algorithm> #define fo(i,a,b) for(int i=a;i<=b;i++) #define N 100005 using namespace std; typedef long long ll; const int mo=1000000000+7; ll ans,n,m,p ,mu ; bool bz ; ll calc(ll n,ll m) { ll ans=0; for(ll l=1,r;l<=n;l=r+1) { r=min(n/(n/l),m/(m/l)); ans+=(mu[r]-mu[l-1])*(n/l)*(m/l); } return ans; } int main() { scanf("%lld%lld",&n,&m); if (n>m) swap(n,m);mu[1]=1; fo(i,2,n) { if (!bz[i]) p[++p[0]]=i,mu[i]=-1; fo(j,1,p[0]) { int k=p[j]*i;if (k>n) break; bz[k]=1;if (!(i%p[j])) break; mu[k]=-mu[i]; } } fo(i,1,n) mu[i]+=mu[i-1]; for(ll l=1,r;l<=n;l=r+1) { r=min(n/(n/l),m/(m/l)); ans+=(r+l)*(r-l+1)/2*calc(n/l,m/l); } printf("%lld\n",ans*2-n*m); }
相关文章推荐
- ISLR读书笔记(2)线性回归
- 机器学习之决策树
- oracle ebs database升级11.1.0.7到11.2.04-
- MySQL 按日、周、月分组统计数据
- 【资源】NOIP2013测试数据senior/junior 普及/提高 数据
- PPT演讲能力让人汗颜?因为你开组会时不认真!
- 3、ubuntu 下编译 linux 内核时无法使用 make menuconfig
- 音视频播放类库总结
- 第4章 文件管理
- Android——DrawerLayout滑动范围的设置
- BZOJ 3576 江南乐
- Spring@Autowired注解与自动装配
- DOM编程艺术学习(三)
- 带权图
- CTF【每日一题20160615】
- uitextfiled uitextview过滤emoji符号 ios
- Java反射机制
- ubuntu安装redis
- Java中把JSON和List结果集互转的代码片段整理
- IPC基础概念Serializable、Parcelable、Binder