码迷,mamicode.com
首页 > 其他好文 > 详细

[NOI2010][bzoj2005] 能量采集 [欧拉函数+分块前缀和优化]

时间:2018-03-02 01:25:30      阅读:154      评论:0      收藏:0      [点我收藏+]

标签:phi   new   row   etc   cli   body   overflow   i++   .com   

题面:

传送门

思路:

稍微转化一下,可以发现,每个植物到原点连线上植物的数量,等于gcd(x,y)-1,其中xy是植物的横纵坐标

那么我们实际上就是要求2*sigma(gcd(x,y))-n*m了

又有某不知名神奇定理:一个数的所有因子的phi之和等于这个数本身,其中phi是欧拉函数

因此题目转化为求如下:

 技术分享图片

我们把式子变个型,就成了如下式子:

技术分享图片

然后一个前缀和优化,O(n+sqrt(n))解决

Code:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #define ll long long
 6 using namespace std;
 7 inline ll read(){
 8     ll re=0,flag=1;char ch=getchar();
 9     while(ch>9||ch<0){
10         if(ch==-) flag=-1;
11         ch=getchar();
12     }
13     while(ch>=0&&ch<=9) re=(re<<1)+(re<<3)+ch-0,ch=getchar();
14     return re*flag;
15 }
16 ll phi[100010],pri[100010],cnt,pre[100010];
17 void init(){
18     phi[1]=pre[1]=1;ll i,j,k;
19     for(i=2;i<=100010;i++){
20         if(!phi[i]) phi[i]=i-1,pri[++cnt]=i;
21         for(j=1;(j<=cnt)&&(i*pri[j]<=100010);j++){
22             if(i%pri[j]) phi[i*pri[j]]=phi[i]*(pri[j]-1);
23             else{phi[i*pri[j]]=phi[i]*pri[j];break;}
24         }
25         pre[i]=pre[i-1]+phi[i];
26 //        if(i<=10) cout<<"phi "<<i<<" "<<phi[i]<<"\n";
27     }
28 }
29 ll n,m;ll ans;
30 int main(){
31     init();ll i,j;
32     n=read();m=read();
33     if(n>m) swap(n,m);
34     for(i=1;i<=n;i=j+1){
35         j=min(n/(n/i),m/(m/i));
36         ans+=(ll)(n/i)*(m/i)*(pre[j]-pre[i-1]);
37     }
38     printf("%lld\n",ans*2-n*m);
39 }

 

 

 

ni=1mi=1d|m?d|ndphi(d)

ni=1mi=1d|m?d|ndphi(d)

[NOI2010][bzoj2005] 能量采集 [欧拉函数+分块前缀和优化]

标签:phi   new   row   etc   cli   body   overflow   i++   .com   

原文地址:https://www.cnblogs.com/dedicatus545/p/8490836.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!