UVA - 11426 GCD - Extreme (II)(欧拉函数筛选法+欧拉函数”倍数关系“)

原题地址:
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2421

给定N的值,您必须找到G的值.G的定义如下:

这里GCD(i,j)表示整数i和整数j的最大公约数。
对于那些无法理解求和符号的人,G的含义在
以下代码:

G =0;
for(I= 1; I <N;i++)
for(J =+ 1;Ĵ<= N; J ++)
{
G += GCD(I,J);
}

这里gcd()是一个找到的函数
两者中最大的共同除数
输入数字
Input
输入文件最多包含100行输入。 每行包含整数 N(1 < N < 4000001)
N的含义在问题陈述中给出。 输入由包含单个的行终止0。
Output
对于每行输入产生一行输出。 该行包含相应的G值
N.G的值将适合64位有符号整数。
样本输入
10
100
200000
0
样本输出
67
13015
143295493160
拿7举例,如果输入的是7:

i 2 3 4 5 6 7
gcd竖着相加 1 2 4 4 9 6
i jgcd(i,j) 1 2(1)互质 1 3(1)互质 1 4(1)互质 1 5(1)互质 1 6(1)互质 1 7(1)互质
i j gcd(i,j) 2 3(1)互质 2 4(2)由gcd(1,2)*2得 2 5(1)互质 2 6(2)由gcd(1,3)*2得 2 7(1)互质
i jgcd(i,j) 3 4(1)互质 3 5(1)互质 3 6(3)由gcd(1,2)*3得 3 7(1)互质
i jgcd(i,j) 4 5(1)互质 4 6(2)由gcd(2,3)*2得 4 7(1)互质
i jgcd(i,j) 5 6(1)互质 5 7(1)互质
i jgcd(i,j) 6 7(1)互质
i jgcd(i,j)

发现:gcd(x,y)=z, gcd(2x,2y) = 2z,gcd(3x,3y)=3z;

gcd(x,y)中x与y互质

竖着为一组:每组的和=互质的数+倍数关系得到的数
互质的数由欧拉定理筛选法得到
互质也用倍数筛选法得到

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll; 
const ll MAXN = 4000006;
ll a[MAXN];
ll b[MAXN];
ll c[MAXN];
ll n,ans,i,j,sum;

void eular()//欧拉筛选法
{
    memset(a,0,sizeof(a));
    a[1]=1;
    for(i=2;i<=MAXN;i++){
        if(!a[i]){
            for(j=i;j<=MAXN;j+=i){
                if(!a[j])
                    a[j] = j;
                a[j] = a[j]/i*(i-1);
            }
        }
    }
}

void zhen()//
{
    memset(b,0,sizeof(b));

    for(i=2;i<MAXN;i++)
    {
        b[i] += a[i];/*将此组的互质数加到b[i]中,除了2以外的第二步,
                        完成后将其打表到c[]中*/
        if(i!=2) c[i] = b[i]+c[i-1];
        else c[i] = b[i];

        for(j=2*i;j<MAXN;j+=i){//对于除了2以外的其它数,这里是第一步;
            b[j] += (a[i]*(j/i));//将最开始的互质的加倍并加到相应的b[j]中,
        }
    }
}
int main()
{
    eular();
    zhen();

    while(scanf("%lld",&n) && n){
            printf("%lld\n",c[n]);
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/orange1710/article/details/81505352