[FZSZOJ 1029] 观察者加强版
1029: 观察者加强版
时间限制: 1 Sec题目描述
魔法学院的期末考开始了。
校长Jacobi用魔法在考场生成了一个观察者,以观察考场情况。
整个考场可以看成一个xOy平面,N*N个考生的坐标为(p,q) (1<=p,q<=N, p,q∈Z+),而观察者的坐标为(0,0)。
但是问题来了,就算在把考生抽象成点的理想情况下,Jacobi的观察者也看不到所有考生的动向,这是因为有一些考生被另一些考生遮住了。为了看到被遮住的考生,Jacobi在观察者上附加了魔法”Mana Preception”。现在观察者可以成功看到所有考生,但是看到一个考生需要消耗Jacobi (观察者和该考生的连线穿过的考生数目+1) 单位的魔力。
现在Jacobi想知道若他的观察者能监视整个考场,他需要消耗多少的魔力。
输入
输入文件watcher.in的第一行包含一个正整数N。
输出
输出文件watcher.out包含一个正整数,意义见问题描述。
样例输入
3
样例输出
12
提示
[数据规模]
对于40%的数据:N<=1000。
对于80%的数据:N<=1000000。
对于100%的数据:1<=N<=10000000。
[注意事项]
本题代码长度不得超过2KB。
【题解】
哎,ysy还是比我强啊,我们问了下cyh才推出来。
本题目为莫比乌斯反演。
推导过程见上方
我们枚举D即可,复杂度为O(n)
前面都可以预处理滴。
主要是,最后那个是可以预处理,i要怎么乘上去呢?用等差数列求和即可。
因为对于每块的后面那一坨东西,除了i都是不变的,那么提出来一下就ok啦。
1 #include<stdio.h> 2 #include<iostream> 3 using namespace std; 4 int mu[10000001]; 5 int n; 6 int zs[10000001]; 7 int prime[1000001],tot; 8 long long ans=0; 9 int f[10000001]; 10 int main() { 11 scanf("%d",&n); 12 for(int i=2;i<=n;++i) { 13 if(!zs[i]) { 14 zs[i]=i; 15 prime[++tot]=i; 16 } 17 for (int j=1;j<=tot&&i*prime[j]<=n;++j) { 18 zs[i*prime[j]]=prime[j]; 19 if(i%prime[j]==0) break; 20 } 21 } 22 f[1]=1; 23 for (int i=2;i<=n;++i) if(zs[i/zs[i]]!=zs[i]) f[i]=f[i/zs[i]]*-1; 24 int last1; 25 for (int i=1;i<=n;i=last1+1) { 26 last1=n/(n/i); 27 for (int r=i;r<last1;++r) f[last1]+=f[r]; 28 if(f[last1]!=0) { 29 long long sum=0; 30 int last2=n/i; 31 int last3; 32 for (int j=1;j<=last2;j=last3+1) { 33 last3=last2/(last2/j); 34 sum+=(long long)(last2/j)*(last2/j)*(j+last3)*(last3-j+1)/2; 35 } 36 ans+=sum*f[last1]; 37 } 38 } 39 printf("%lld\n",ans); 40 return 0; 41 }
这篇文章由TonyFang发布。
所有解释权归TonyFang所有。
Mailto: tony-fang@map-le.net