标签:
题意:求sum(gcd(i,j),1<=i<j<=n)。
思路:首先可以看出可以递推求出ans[n],因为ans[n-1]+f(n),其中f(n)表示小于n的数与n的gcd之和
问题转化为了求f(n),因为小于n的数与n的gcd一定是n的因数,
所以f(n)可以表示为sum(i)*i,其中sum(i)表示所有和n的gcd为i的数的数量,我们要求满足gcd(a, n) = i,的个数,可以转化为求gcd(a/i, n/i) = 1的个数,
于是可以发现sun(i) = phi(n/i),这里枚举n的因数的方法仿照素数筛法,时间复杂度为O(nlogn).
#include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include<algorithm> #include<vector> #include<map> #include<queue> #include<stack> #include<string> #include<map> #include<set> #include<ctime> #define eps 1e-6 #define LL long long #define pii (pair<int, int>) //#pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; const int maxn = 5000000; //const int INF = 0x3f3f3f3f; int n; LL ans[5000000]; int phi[maxn]; void phi_table(int n) { for(int i = 2; i <= n; i++) phi[i] = 0; phi[1] = 1; for(int i = 2; i <= n; i++) if(!phi[i]) for(int j = i; j <= n; j+=i) { if(!phi[j]) phi[j] = j; phi[j] = phi[j] / i * (i-1); } } void init() { phi_table(4000000); ans[1] = 0; for(int i = 1; i <= 4000000; i++) { for(int j = i*2; j <= 4000000; j+=i) { ans[j] += phi[j/i]*i; } } for(int i = 2; i <= 4000000; i++) ans[i] += ans[i-1]; } int main() { //freopen("input.txt", "r", stdin); init(); //cout << phi[3] << endl; while(scanf("%d", &n) == 1 && n) { cout << ans[n] << endl; } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
UVA 11426 GCD - Extreme (II) (数论|欧拉函数)
标签:
原文地址:http://blog.csdn.net/u014664226/article/details/47761045