UVA-11426 GCD-Extreme(II) 尤拉函式+推公式
阿新 • • 發佈:2018-12-16
感覺很考驗思維的一道題。。我太菜了...除了最樸素的暴力就想不出來別的了QAQ..
主要就是以下三點:
1.g[n]=g[n-1]+b[n],b[n]表示1到n-1與n的gcd的和
2.b[n]=∑(a[i]*i) (0<i<n),a[i]表示1到n-1內滿足gcd(n,x)=i的x的個數,即滿足gcd(n/i,x/i)=1
3.a[i]=eul[n/i](n為i的倍數)
寫程式碼時也是有技巧的Orz,就是把n放在內層,這樣會快很多。。
附上AC程式碼:
#include<cstdio> #include<cmath> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define ll long long const ll MOD=1e9+(ll)7; const int MAX=4000002; int n; int eul[MAX]; void getEul()//尤拉函式 { eul[1]=1; for(int i=2;i<MAX;i++) eul[i]=i; for(int i=2;i<MAX;i++) if(eul[i]==i) for(int j=i;j<MAX;j+=i) eul[j]=eul[j]/i*(i-1); } ll b[MAX]; ll g[MAX]; void init() { getEul(); memset(b,0,sizeof(b)); memset(g,0,sizeof(g)); /*b[1]=1;g[1]=0; for(int j=2;j<MAX;j++)//對應n { for(int i=2;i<=j;i++) { b[j]+=i*eul[(j/i)]; } g[j]=g[j-1]+b[j]; }*/ for(int i=1;i<MAX;i++) { for(int j=i*2;j<MAX;j+=i)//對應n b[j]+=i*eul[(j/i)]; } for(int i=2;i<MAX;i++) g[i]=g[i-1]+b[i]; } int main() { //cout<<"begin"<<endl; init(); while(scanf("%d",&n)==1) { if(n==0) break; printf("%lld\n",g[n]); } return 0; }