正文前的一些提示:打 UVA
的題時,輸出後一定要有一個空行,否則等待您的,就是一次又一次的 WA
。
UVA11426 GCD Extreme(II)
[Problem]
-
給定一個數 n,求:
i=1∑nj=i+1∑ngcd(i,j)
-
2≤n≤4×106,多組數據,輸入以 0 結束。保證答案在 long long
範圍內。
[Solution]
記 fi=j=1∑i−1gcd(j,i),則答案 Si=j=2∑nfj。
求出了所有的 fi(2≤i≤N) 後(N=4×106),就可以用 O(N) 的時間求出所有的 Si(2≤i≤N)。
現在,讓我們考慮如何求出 fi(2≤i≤N)。
枚舉 d,代表 gcd(j,i)=d,假設這樣的 j 有 k 個,則對答案的貢獻爲 k×d。
接下來,考慮如何求出 k 的值。顯然,i,j 一定滿足 d∣i,d∣j,且 di,dj 互質。
簡單地證明一下:顯然 i,j 一定是滿足 d∣i,d∣j 的,否則 gcd(i,j)=d。爲什麼 di,dj 互質呢?
考慮反證法。假設 di,dj 不互質,記其最大公約數爲 g。那麼 g 一定也是 i,j 的因子,而且 d×g∣i,d×g∣j,即 d×g 也是 i,j 的公約數,這與 d 是 i,j 的最大公約數矛盾。
有了這個定理,所以一對可行的 (i,j) 一定與一對互質的數 (di,dj) 一一對應。而因爲 di,dj 互質,所以這樣的 dj 一共有 φ(di) 個,故這樣的 j 一共有 φ(di) 個。
所有的 φ(i)(1≤i≤N) 可以 O(N) 求出,而枚舉 d 並計算 fi(2≤i≤N) 是 O(N×logN) 的,求出 Si(2≤i≤N) 是 O(N) 的,輸出答案是 O(1) 的。故總的時間複雜度爲 O(N×N+T),其中 T 是一共的數據個數。
[code]
const int N=4e6+100;
typedef long long ll;
int n,phi[N];ll S[N],f[N];
int prime[N],g[N],tot;
inline void get_prime(int N){
tot=0;phi[1]=1;
for(int i=2;i<=N;i++){
if (!g[i]){
phi[i]=i-1;
g[i]=prime[++tot]=i;
}
for(int j=1;j<=tot;j++){
if (1ll*i*prime[j]>N) break;
register int t=i*prime[j];
phi[t]=phi[i]*(prime[j]-(prime[j]<g[i]));
g[t]=prime[j];
if (prime[j]==g[i]) break;
}
}
}
int main(){
get_prime(4e6);
for(int i=1;i<=(int)4e6;i++)
for(int j=i*2;j<=(int)4e6;j+=i)
f[j]+=1ll*i*phi[j/i];
S[2]=f[2];
for(int i=3;i<=(int)4e6;i++)
S[i]=S[i-1]+f[i];
while (~scanf("%d",&n)&&n)
printf("%lld\n",S[n]);
return 0;
}