正文前的一些提示:打 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;
}