hdu 3875 Euclidean Algorithm 计算sigma gcd and lcm %p

Problem Description
wr recently learned the Euclidean algorithm to solve the greatest common divisor,then he realized that the algorithm can also be able to solve the least common multiple.In order to train the skill of code,he find a number p(1<=p<=2^25)and a number q(1<=q<=2^25) then he got n=p*q,he calculated a 1=∑gcd(i, n) 1<=i <=n and a 2= ∑lcm(i, n) 1<=i <=n,he wants to know if a2-a1 is the multiple of c(1<=c<=10^9)
 

Input
The first line contains the number of scenarios.
Every scenario consists of a single line containing two integers n and c separated by a space.
 

Output
for every scenario print a single line contain "yes" or "no"
if the difference is the multiple of c print "yes",otherwise print "no"
 

Sample Input
  
  
2 6 100 4 2
 

Sample Output
  
  
no yes

//


#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<ctime>
#define bignum unsigned long long
using namespace std;
//求a,b的最大公约数
bignum gcd(bignum a,bignum b)
{
    return b==0?a:gcd(b,a%b);
}
//求a*b%c,因为a,b很大,所以要先将b写成二进制数,再加:例如3*7=3*(1+2+4);
bignum mulmod(bignum a,bignum b,bignum c)
{
    bignum cnt=0,temp=a;
    while(b)
    {
        if(b&1) cnt=(cnt+temp)%c;
        temp=(temp+temp)%c;
        b>>=1;
    }
    return cnt;
}
//求a^b%c,再次将b写成二进制形式,例如:3^7=3^1*3^2*3^4;
bignum powmod(bignum a,bignum b,bignum c)
{
    bignum cnt=1,temp=a;
    while(b)
    {
        if(b&1) cnt=mulmod(cnt,temp,c);//cnt=(cnt*temp)%c;
        temp=mulmod(temp,temp,c);//temp=(temp*temp)%c;
        b>>=1;
    }
    return cnt;
}
//Miller-Rabin测试n是否为素数,1表示为素数,0表示非素数
int pri[10]={2,3,5,7,11,13,17,19,23,29};
bool Miller_Rabin(bignum n)
{
    if(n<2) return 0;
    if(n==2) return 1;
    if(!(n&1)) return 0;
    bignum k=0,m;
    m=n-1;
    while(m%2==0) m>>=1,k++;//n-1=m*2^k
    for(int i=0;i<10;i++)
    {
        if(pri[i]>=n) return 1;
        bignum a=powmod(pri[i],m,n);
        if(a==1) continue;
        int j;
        for(j=0;j<k;j++)
        {
            if(a==n-1) break;
            a=mulmod(a,a,n);
        }
        if(j<k) continue;
        return 0;
    }
    return 1;
}
//pollard_rho 大整数分解,给出n的一个非1因子,返回n是为一次没有找到
bignum pollard_rho(bignum C,bignum N)
{
    bignum I, X, Y, K, D;
    I = 1;
    X = rand() % N;
    Y = X;
    K = 2;
    do
    {
        I++;
        D = gcd(N + Y - X, N);
        if (D > 1 && D < N) return D;
        if (I == K) Y = X, K *= 2;
        X = (mulmod(X, X, N) + N - C) % N;
    }while (Y != X);
    return N;
}
//找出N的最小质因数
bignum rho(bignum N)
{
    if (Miller_Rabin(N)) return N;
    do
    {
        bignum T = pollard_rho(rand() % (N - 1) + 1, N);
        if (T < N)
        {
              bignum A, B;
              A = rho(T);
              B = rho(N / T);
              return A < B ? A : B;
        }
    }
    while(1);
}
//N分解质因数,这里是所有质因数,有重复的
bignum AllFac[1100];
int Facnum;
void findrepeatfac(bignum n)
{
    if(Miller_Rabin(n))
    {
        AllFac[++Facnum]=n;
        return ;
    }
    bignum factor;
    do
    {
        factor=pollard_rho(rand() % (n - 1) + 1, n);
    }while(factor>=n);
    findrepeatfac(factor);
    findrepeatfac(n/factor);
}
//求N的所有质因数,是除去重复的
bignum Fac[1100];
int num[1100];
int len;//0-len
void FindFac(bignum n)
{
    len=0;
    //初始化
    memset(AllFac,0,sizeof(AllFac));
    memset(num,0,sizeof(num));
    Facnum=0;
    findrepeatfac(n);
    sort(AllFac+1,AllFac+1+Facnum);
    Fac[0]=AllFac[1];
    num[0]=1;
    for(int i=2;i<=Facnum;i++)
    {
        if(Fac[len]!=AllFac[i])
        {
            Fac[++len]=AllFac[i];//important
        }
        num[len]++;
    }
}
//求n的欧拉函数值
bignum oula(bignum n)
{
    FindFac(n);
    bignum cnt=n;
    for(int i=0;i<=len;i++)
    {
        cnt-=cnt/Fac[i];
    }
    return cnt;
}
//枚举n的所有因子  cnt
/*bignum Fac[1100];
int num[1100];
int len;//0-len
*/
bignum yinzi[100000];
bignum yinzinum;//初始化在main中(0-yinzinum-1)
void dfs(int id,bignum cnt)
{
    yinzi[yinzinum++]=cnt;
    if(id==len+1)
    {
        return ;
    }
    bignum temp=1;
    for(int i=0;i<=num[id];i++)
    {
        dfs(id+1,cnt*temp);
        temp*=Fac[id];
    }
}
bignum sigma_gcd(bignum n)//n>1
{
    if(n==1) return 1;
    FindFac(n);
    bignum ret=1;
    for(int i=0;i<=len;i++)
    {
        bignum tmp=1;
        for(int j=0;j<num[i]-1;j++) tmp*=Fac[i];//可以%p
        ret=ret*(tmp*Fac[i]+(num[i]*tmp)*(Fac[i]-1));//%p
    }
    return ret;
}
bignum sigma_gcd(bignum n,bignum p)//n>1  sigma_gcd(i,n)%p
{
    if(n==1) return 1%p;
    FindFac(n);
    bignum ret=1;
    for(int i=0;i<=len;i++)
    {
        bignum tmp=1;
        for(int j=0;j<num[i]-1;j++) tmp=(tmp*Fac[i])%p;//可以%p
        ret=(ret*(tmp*Fac[i]+((num[i]*tmp)%p)*(Fac[i]-1)))%p;//%p
    }
    return ret;
}
bignum sigma_lcm(bignum n,bignum p)//n>1 sigma_lcm(i,n)%p
{
    if(n==1) return 1%p;
    FindFac(n);
    bignum pp=p*2;
    bignum ret=1;
    for(int i=0;i<=len;++i)
    {
        bignum tmp=1;
        for(int j=0;j<2*num[i];++j)tmp=tmp*Fac[i];//不用%pp,下面要tmp-1
        ret=(ret*(((tmp-1)/(Fac[i]+1)*Fac[i]+1))%pp)%pp;
    }
    ret=((n*(ret+1))%pp)/2;
    return ret;
}
int main()
{
    srand(time(NULL));
    int ci;scanf("%d",&ci);
    while(ci--)
    {
        bignum n,p;scanf("%I64d%I64d",&n,&p);
        if(sigma_gcd(n,p)==sigma_lcm(n,p)) printf("yes\n");
        else printf("no\n");
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值