1. 程式人生 > >GCD - Extreme (II) UVA - 11426(歐拉函數!!)

GCD - Extreme (II) UVA - 11426(歐拉函數!!)

sin spa end 是不是 ++ size stream ont 出了

G(i) = (gcd(1, i) + gcd(2, i) + gcd(3, i) + .....+ gcd(i-1, i))

ret = G(1) + G(2) + G(3) +.....+ G(n);

對於gcd(x,i),我們設gcd(x,i) = m 即x和i的最大公約數為m 則x/m 和 i/m 互質 然後我們求出於i/m互質的有多少個 是不是就是求出了與i最大公約數為m的有多少個。。用歐拉函數既能求出個數 。。。即為phi(i/m)個 用雙重循環 外層循環為m內層循環為i, i從m+m開始遍歷每次加m, 然後循環裏 G(i)+= phi(i/m)*m 則就求出了G(i)

最後累加G(i) 即為答案ret

數組要開long long

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#define mem(a, b) memset(a, b, sizeof(a))
using namespace std;
const int maxn = 4000001, INF = 0x7fffffff;
long long
A[maxn], G[maxn], ret[maxn]; void init() { for(int i=1; i<maxn; i++) A[i] = i; for(int i=2; i<maxn; i++) if(A[i] == i) for(int j=i; j<maxn; j+=i) A[j] = A[j]/i*(i-1); } int main() { init(); for(int m=1; m<maxn; m++) for
(int i=m+m; i<maxn; i+=m) G[i] += A[i/m] * m; for(int i=2; i<maxn; i++) ret[i] = ret[i-1] + G[i]; int n; while(cin>> n && n) { cout<< ret[n] <<endl; } return 0; }

GCD - Extreme (II) UVA - 11426(歐拉函數!!)