zoukankan      html  css  js  c++  java
  • [UVA11426] GCD-Extreme(II)

    Description

    输入正整数 (n),求 (gcd(1,2)+gcd(1,3)+gcd(2,3)+...+gcd(n-1,n)),即所有满足 (1leq i<jleq n) 的所有正整数对 ((i,j)) 所对应的 (gcd(i,j)) 之和。

    Solution

    (f(n)=gcd(1,n)+gcd(2,n)+...+gcd(n-1,n)),则所求答案为 (ans(n)=f(2)+f(3)+f(4)+...+f(n))。只需求出 (f(n)),就可以递推出所有答案:(ans(n)=ans(n-1)+f(n))。因此,本题的重点在于如何计算 (f(n))

    注意到所有 (gcd(x,n)) 的值都是 (n) 的约数,可以按照这个约数进行分类,用 (g(i,n)) 表示满足 (gcd(x,n)=i;&&;x<n) 的正整数 (x) 的个数,则 (f(n)=sum limits_{imid n} g(i,n) imes i)。注意到 (gcd(x,n)=i) 的充要条件是 (gcd(x/i,n/i)=1),因此满足条件的 (x/i)(phi(n/i)) 个,说明 (gcd(x,n)=phi(n/i))

    所以对于每个数 (i),枚举它的倍数 (j),令 (f(j)+=i imes phi(j/i)) 即可。

    Code

    #include<cstdio>
    #define N 4000005
    #define int long long
    
    int phi[N];
    int mindiv[N];
    int f[N],ans[N];
    int prime[N],primecnt;
    
    void init(){
    	for(int i=2;i<=N;i++){
    		if(!mindiv[i]){
    			phi[i]=i-1;
    			mindiv[i]=i;
    			prime[++primecnt]=i;
    		}
    		for(int j=1;j<=primecnt;j++){
    			if(i*prime[j]>N) break;
    			if(prime[j]>mindiv[i]) break;
    			mindiv[i*prime[j]]=prime[j];
    			phi[i*prime[j]]=phi[i]*(i%prime[j]?prime[j]-1:prime[j]);
    		}
    	}
    }
    
    signed main(){
    	init();
    	for(int i=1;i<=N;i++){
    		for(int j=(i<<1);j<=N;j+=i)
    			f[j]+=phi[j/i]*i;
    	}
    	ans[2]=f[2];
    	for(int i=3;i<=N;i++)
    		ans[i]=ans[i-1]+f[i];
    	int x;
    	while(scanf("%lld",&x)){
    		if(!x) return 0;
    		printf("%lld
    ",ans[x]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    贪心策略---不重叠的区间个数
    贪心策略---分配饼干
    双指针---最长子序列
    双指针---回文字符串
    双指针---反转字符串中的元音字符
    双指针---两数平方和
    双指针---有序数组的TWO SUM
    排序---小结
    排序---桶排序
    变量的解构赋值
  • 原文地址:https://www.cnblogs.com/YoungNeal/p/9102468.html
Copyright © 2011-2022 走看看