码迷,mamicode.com
首页 > 其他好文 > 详细

51 NOD 1188 最大公约数之和 V2(基础数论)

时间:2016-08-10 17:41:21      阅读:448      评论:0      收藏:0      [点我收藏+]

标签:

传送门
给出一个数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=2i?1j=1GCD(i,j)

那么以前讲过一道题是给两个数 nm (mn) ,让你求 [1,n]mGCD 是和多少。

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=2i?1j=1GCD(i,j)

=Ni=2i?1j=1,j|iphi(ij)?j

=Ni=1Nj=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;
}

51 NOD 1188 最大公约数之和 V2(基础数论)

标签:

原文地址:http://blog.csdn.net/qingshui23/article/details/52174475

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!