您的位置:首页 > 其它

uva 11424 && 11426 GCD - Extreme(数论:欧拉函数)

2014-11-22 16:33 495 查看
看着白书做的,方法太巧妙了。。。

不过也总算掌握了算区间GCD的方法

我们令f(n) = gcd(1, n) + gcd(2, n) + ... + gcd(n-1, n)

则对应的结果s(n) = f(2) + f(3) + ... + f(n)

所以s(n) = s(n-1)+f(n)

因此我们只需求出所有的f(n),在递推即可

取g(n, i)表示小于n且与n的gcd值等于i的数x的个数(gcd(n, x) = i)

则f(n) = 1*gcd(n, 1) + 2*gcd(n ,2) + ...

而gcd(n, x) = i即gcd(n/i, x/i) = 1

所以g(n, i) == phi(n/i)

代码如下:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define MAXN 4000001
using namespace std;

int phi[MAXN+10];
LL f[MAXN+10], s[MAXN+10];

void phi_table(int n) {
memset(phi, 0, sizeof(phi));
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);
}
}
}
return ;
}

int main(void) {
int n;
phi_table(MAXN);
memset(s, 0, sizeof(s));
memset(f, 0, sizeof(f));
for(int i=1; i<=MAXN; ++i) {
for(int j=i*2; j<=MAXN; j+=i)
f[j] += i*phi[j/i];
}
s[2] = f[2];
for(int i=3; i<=MAXN; ++i)
s[i] = s[i-1]+f[i];

while(~scanf("%d", &n) && n) {
cout << s
<< endl;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: