【BZOJ】【2005】【NOI2010】能量采集
欧拉函数
玛雅,我应该先看看JZP的论文的……贾志鹏《线性筛法与积性函数》例题一
这题的做法……仔细想下可以得到:$ans=2*\sum_{a=1}^n\sum_{b=1}^m gcd(a,b)-n*m$
那么重点就在于算$\sum_{a=1}^n\sum_{b=1}^m gcd(a,b)$这个东西
copy一下JZP的推导过程:
$$ \begin{aligned} \sum_{a=1}^n \sum_{b=1}^m gcd(a,b) &= \sum_{a=1}^n \sum_{b=1}^m \sum_{d|gcd(a,b)} \varphi(d) \\ &= \sum_{a=1}^n \sum_{b=1}^m \sum_{d|a and d|b} \varphi(d) \\ &= \sum \varphi(d) \sum_{1 \leq a \leq n \&\& d|a} \sum_{1 \leq b \leq m \&\& d|b} 1 \\ &= \sum \varphi(d) ( \sum_{1 \leq a \leq n \&\& d|a} 1) * ( \sum_{1 \leq b \leq m \&\& d|b} 1) \\ &= \sum \varphi(d) \left\lfloor \frac{n}{d} \right\rfloor \left\lfloor \frac{m}{d} \right\rfloor \end{aligned} $$
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /************************************************************** 2 Problem: 2005 3 User: Tunix 4 Language: C++ 5 Result: Accepted 6 Time:40 ms 7 Memory:2152 kb 8 ****************************************************************/ 9 10 //BZOJ 2005 11 #include<cstdio> 12 #include<cstring> 13 #include<cstdlib> 14 #include<iostream> 15 #include<algorithm> 16 #define rep(i,n) for(int i=0;i<n;++i) 17 #define F(i,j,n) for(int i=j;i<=n;++i) 18 #define D(i,j,n) for(int i=j;i>=n;--i) 19 using namespace std; 20 typedef long long LL; 21 inline int getint(){ 22 int r=1,v=0; char ch=getchar(); 23 for(;!isdigit(ch);ch=getchar()) if(ch=='-')r=-1; 24 for(; isdigit(ch);ch=getchar()) v=v*10+ch-'0'; 25 return r*v; 26 } 27 const int N=1e5+10,INF=~0u>>2; 28 /*****************template**********************/ 29 int phi[N],prime[N],tot,n,m; 30 bool check[N]; 31 void getphi(int n){ 32 memset(check,0,sizeof check); 33 phi[1]=1; 34 int tot=0; 35 F(i,2,n){ 36 if(!check[i]){ 37 prime[++tot]=i; 38 phi[i]=i-1; 39 } 40 F(j,1,tot){ 41 if(i*prime[j]>n) break; 42 check[i*prime[j]]=1; 43 if(i%prime[j]==0){ 44 phi[i*prime[j]]=phi[i]*prime[j]; 45 break; 46 } 47 else phi[i*prime[j]]=phi[i]*(prime[j]-1); 48 } 49 } 50 } 51 int main(){ 52 n=getint(); m=getint(); 53 if (n>m) swap(n,m); 54 getphi(N-1); 55 LL ans=0; 56 F(i,1,n) 57 ans+=(LL)phi[i]*(n/i)*(m/i); 58 printf("%lld\n",ans*2-(LL)n*m); 59 return 0; 60 }