1. 程式人生 > >P2303 [SDOi2012]Longge的問題

P2303 [SDOi2012]Longge的問題

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)++)
#define
Bor(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; } int
main(){ 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的問題