[FZSZOJ 1029] 观察者加强版

1029: 观察者加强版

时间限制: 1 Sec
内存限制: 128 MB

题目描述

魔法学院的期末考开始了。
校长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 }
View Code

 

posted @ 2015-06-23 21:24  TonyFang  阅读(240)  评论(0编辑  收藏  举报