[BZOJ2190][SDOI2008]仪仗队 数学


题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2190

看到这道题首先想到了NOI2010的能量采集,这不就是赤裸裸的弱化版吗?直接上莫比乌斯反演就行了。

令$f(d)=\sum_{i=1}^n\sum_{j=1}^n[gcd(i,j)==d]$

则有$g(d)=\sum_{i=1}^n\sum_{j=1}^n[d|gcd(i,j)]=\frac{n}{d}\frac{n}{d}=\sum_{d|n}f(d)$

由莫比乌斯反演得$f(d)=\sum_{d|n}μ(\frac{n}{d})F(n)=\sum_{x=1}^nμ(x)\frac{n}{dx}\frac{n}{dx}$

然而并没有写,因为发现有更简单的做法。

其实我们发现除开对角线单看一半,就是求小于n的x的phi值的和是多少,根据$gcd(a,b)=1$容易观察出来,然后最后加上对角线还有x轴y轴上三个特殊的点就可以了。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 typedef long long ll;
 6 int p[40010],cnt=0;
 7 int phi[40010];
 8 bool vis[40010];
 9 void sieve(){
10     for(int i=2;i<=40000;i++){
11         if(!vis[i]){
12             p[++cnt]=i;
13             phi[i]=i-1;
14         }
15         for(int j=1;p[j]*i<=40000&&j<=cnt;j++){
16             vis[i*p[j]]=true;
17             if(i%p[j]==0){
18                 phi[i*p[j]]=phi[i]*p[j];
19                 break;
20             }
21             phi[i*p[j]]=phi[i]*(p[j]-1);
22         }
23     }
24 }
25 int N;
26 int main(){
27     sieve();
28     scanf("%d",&N);
29     ll ans=0;
30     for(int i=2;i<N;i++) ans+=phi[i];
31     ans=ans*2+3;
32     printf("%lld\n",ans);
33     return 0; 
34 }

优质内容筛选与推荐>>
1、Nio-Socket-SelectionKey
2、C++对数组进行复制
3、网上的腾讯php面试题 (有答案版本)
4、sscanf简介
5、【运维实战】一次linux日志分割之路——将日志按照每小时进行分割,并按照“日期-小时”格式保存


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号