原题地址:
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;
}