nyoj-1007 GCD【欧拉函数】

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013852115/article/details/82859712

GCD

时间限制:1000 ms  |  内存限制:65535 KB

难度:3

输入

The first line of input is an integer T(T<=100) representing the number of test cases. The following T lines each contains two numbers N and M (1<=N<=10^9, 1<=M<=10^9), representing a test case.

输出

Output the answer mod 1000000007

样例输入

3
1 1
10 2
10000 72

样例输出

1
35
1305000

上传者

ACM_张书军

描述

The greatest common divisor GCD(a,b) of two positive integers a and b,sometimes written (a,b),is the largest divisor common to a and b,For example,(1,2)=1,(12,18)=6.
(a,b) can be easily found by the Euclidean algorithm. Now Carp is considering a little more difficult problem:
Given integers N and M,please answer sum of  X satisfies 1<=X<=N and (X,N)>=M.

思路:

要求gcd(x,n)>=m,可以枚举gcd(x,n),然后乘以一个倍数,就可以得到x,并且这个倍数必须与n互质。

我们要求所有x的和,就可以利用欧拉函数,求出来与n互质的所有数之和,再乘以gcd(x,n),就可以得出在gcd(x,n)下,所有x的和。

euler_sum函数直接照搬大佬的模板。

代码:

#include<bits/stdc++.h>
using namespace std;
#define MAXN 2005
#define ll long long
#define inf 0x3f3f3f3f
#define mod 1000000007
ll n,m;
int euler(int n){ //返回euler(n)
     int res=n,a=n;
     for(int i=2;i*i<=a;i++){
         if(a%i==0){
             res=res/i*(i-1);//先进行除法是为了防止中间数据的溢出
             while(a%i==0) a/=i;
         }
     }
     if(a>1) res=res/a*(a-1);
     return res;
}
ll euler_sum(ll n)
{
    if(n==1 || n==2) return 1;
    return n*euler(n)/2;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lld%lld",&n,&m);
        ll ans=0;
        for(ll i=1;i*i<=n;i++)
        {
            if(n%i==0)
            {
                if(i>=m) ans=(ans+i*euler_sum(n/i))%mod;
                if(n/i>=m && i!=n/i) ans=(ans+(n/i)*euler_sum(i))%mod;
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}
/*
*/

猜你喜欢

转载自blog.csdn.net/u013852115/article/details/82859712