给出一个数N,输出小于等于N的所有数,两两之间的最大公约数之和。计算这段程序
G=0;
for(i=1; i < N;i++)
for(j=i+1;j<=N;j++)
{
G+=gcd(i,j);
}
Input
第1行:1个数T,表示后面用作输入测试的数的数量。(1 <= T <= 50000)
第2 - T + 1行:每行一个数N。(2 <= N <= 5000000)
Output
共T行,输出最大公约数之和。
Input示例
3
10
100
200000
Output示例
67
13015
143295493160
解题思路:
题目要求就是让求 ≤N 的两两之间的最大公约数和,也就是:∑Ni=2∑i?1j=1GCD(i,j)
那么以前讲过一道题是给两个数 n 和 m (m≤n) ,让你求 [1,n] 与 m 的 GCD 是和多少。
设 GCD(m,i)==x, 那么 GCD(m/x,i/x)==1,那么这个问题可以转化为[1,i/x] 区
间中 与 i/x 互素的个数有多少个,求出来之后再乘以 x
就是: ∑ni=1,i|nphi(n/i)?i 其中 phi(i)是i的欧拉函数值
那么我们现在要求的这个问题也可以转为这个:
结果=∑Ni=2∑i?1j=1GCD(i,j)
=∑Ni=2∑i?1j=1,j|iphi(ij)?j
=∑Ni=1∑Nj=2i?phi(j)——(if i?j<=N)
My Code:
/**
2016 - 08 - 10 下午
Author: ITAK
Motto:
今日的我要超越昨日的我,明日的我要胜过今日的我,
以创作出更好的代码为目标,不断地超越自己。
**/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
#include <set>
#include <bitset>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const LL MAXN = 5e6+50;
const double eps = 1e-7;
const double PI = acos(-1.0);
using namespace std;
bool flag[MAXN];///标记数组
LL phi[MAXN];///欧拉函数值,i的欧拉函数值=phi[i]
LL p[MAXN];///素因子的值
LL cnt = 0;
void Get_phi()///筛法求欧拉函数
{
cnt = 0;
memset(flag, true, sizeof(flag));
phi[1] = 1;
for(LL i=2; i<MAXN; i++)///线性筛法
{
if(flag[i])///素数
{
p[cnt++] = i;
phi[i] = i-1;///素数的欧拉函数值是素数 - 1
}
for(LL j=0; j<cnt; j++)
{
if(i*p[j] > MAXN)
break;
flag[i*p[j]] = false;///素数的倍数,所以i*p[j]不是素数
if(i%p[j] == 0)///性质:i mod p == 0, 那么 phi(i * p) == p * phi(i)
{
phi[i*p[j]] = p[j] * phi[i];
break;
}
else
phi[i*p[j]] = (p[j]-1) * phi[i];///i mod p != 0, 那么 phi(i * p) == phi(i) * (p-1)
}
}
}
LL ans[MAXN];
void Init()
{
Get_phi();
memset(ans, 0, sizeof(ans));
for(LL i=1; i<MAXN; i++)
for(LL j=2; j<MAXN; j++)
if(i*j < MAXN)
ans[i*j] += phi[j]*i;
else
break;
for(LL i=1; i<MAXN; i++)
ans[i] += ans[i-1];
}
int main()
{
Init();
LL T, N;
scanf("%I64d",&T);
while(T--)
{
scanf("%I64d", &N);
printf("%I64d\n",ans[N]);
}
return 0;
}
时间: 2024-10-08 03:56:20