GCD

来源:互联网 发布:cnc五轴编程 编辑:程序博客网 时间:2024/05/26 02:54

题目链接

/*    看了挺久的,才大致看懂了是什么意思;    要求给定数的gcd(i,j)  (1<=i<=j<=n)    因为数据很大,故打表是个选择    对于给定的n, a(n) = gcd(1,n)+gcd(2,n) +......+gcd(n-1,n)    故 结果为  sum(n) = a(2) + a(3) + a(4) + ...... + a(n);    sum(n) = sum(n-1) + a(n-1);    所以要求到 a(n)才是关键;    对于 gcd(x,n) = i 的充分必要条件是 gcd(x/i,n/i) = 1;    即 x/i  和 n/i 是互质的,而满足这样的 个数是 eul[n/i](欧拉函数求小于n并与值互质的个数)*/ #include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<queue>#include<algorithm>#define ll long long#define inf 0x3f3f3f3f#define maxn 4000010using namespace std;ll eul[maxn];ll a[maxn];ll b[maxn];void init(){    eul[1] = 1;    for(int i=2;i<maxn;i++)        eul[i] = i;    for(int i=2;i<maxn;i++)        if(eul[i] == i)            for(int j=i;j<maxn;j+=i)                eul[j]=eul[j]/i*(i-1);   // 求出欧拉函数     memset(a,0,sizeof(a));    for(int i=1;i<maxn;i++)      // 类似素数筛法 ,i 是公因子         for(int j=i*2;j<maxn;j+=i)            a[j] += eul[j/i]*i;   // i 为小于 j 的数与  j 的公因子     b[1] = 0;    b[0] = 0;    for(int i=2;i<maxn;i++)        b[i] = b[i-1] + a[i];}int main(){    init();    int x;    while(~scanf("%d",&x) , x)    {        printf("%lld\n",b[x]);    }    return 0;}
0 0
原创粉丝点击