P2303 [SDOi2012]Longge的問題
阿新 • • 發佈:2018-09-22
str register 數據 using 個數 成績 main 輸入格式 limits
題目描述
Longge的數學成績非常好,並且他非常樂於挑戰高難度的數學問題。現在問題來了:給定一個整數N,你需要求出∑gcd(i, N)(1<=i <=N)。
輸入輸出格式
輸入格式:
一個整數,為N。
輸出格式:
一個整數,為所求的答案。
輸入輸出樣例
輸入樣例#1:6
輸出樣例#1:
15
說明
對於60%的數據,0<N<=2^16
對於100%的數據,0<N<=2^32
Solution:
本題數學。
設$f(x)$表示範圍內$gcd(i,j)=x$的數的個數,則$f(x)=\sum_\limits{i=1}^{i\leq n}{(gcd(i,n)=x)}\;=\;\sum_\limits{i=1}^{i\leq \frac{n}{x}}{x*(gcd(i,\frac{n}{x})=1)}\;=\;x*\varphi (\frac{n}{x})$。
所以原式$=\sum_\limits{i|n}^{i\leq n}{i*\varphi (\frac{n}{i})}$。
於是直接暴力根號枚舉n的因子,然後暴力根號篩$\varphi$ 求解就好了,時間復雜度$O(n^{\frac{3}{4}})$(註意開long long,被坑慘了)。
代碼:
/*Code by 520 -- 9.20*/ #include<bits/stdc++.h> #define il inline #define ll long long #define RE register #define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++) #defineBor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--) using namespace std; ll n; ll ans; ll phi(ll x){ ll ans=x; for(ll i=2;i*i<=x;i++) if(x%i==0) { while(x%i==0) x/=i; ans=ans/i*(i-1); } if(x>1) ans=ans/x*(x-1); return ans; } intmain(){ cin>>n; ll i=1; for(i=1;i*i<n;i++) if(n%i==0) ans+=i*phi(n/i)+(n/i)*phi(i); if(i*i==n) ans+=i*phi(i); cout<<ans; return 0; }
P2303 [SDOi2012]Longge的問題