/*
看了挺久的,才大致看懂了是什么意思;
要求给定数的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 4000010
using 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;
}
GCD - Extreme (II) UVA - 11426 (欧拉函数)
最新推荐文章于 2021-05-27 15:33:17 发布