uva 11426 欧拉函数

来源:互联网 发布:mac休眠后继续下载吗 编辑:程序博客网 时间:2024/05/21 10:26

这也是训练赛上的一个题目,题目的要求很简单,就是那个代码所展示的,然后,然后当时就不会了,后来才知道可以用欧拉函数求gcd(i,j);

先说一下如何分析这个题目

我们令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 4000001using 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));    //cout<<phi[12]<<endl;    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[n] << endl;    }}