hdu 4320 Arcane Numbers 1

5 篇文章 0 订阅

Problem Description
Vance and Shackler like playing games. One day, they are playing a game called "arcane numbers". The game is pretty simple, Vance writes down a finite decimal under base A, and then Shackler translates it under base B. If Shackler can translate it into a finite decimal, he wins, else it will be Vance’s win. Now given A and B, please help Vance to determine whether he will win or not. Note that they are playing this game using a mystery language so that A and B may be up to 10^12.
 

Input
The first line contains a single integer T, the number of test cases.
For each case, there’s a single line contains A and B.
 

Output
For each case, output “NO” if Vance will win the game. Otherwise, print “YES”. See Sample Output for more details.
 

Sample Input
  
  
3 5 5 2 3 1000 2000
 

Sample Output
  
  
Case #1: YES Case #2: NO Case #3: YES


代码每次都是差一点点。。。不过在YY情况下,正确的可能确实是很小。

证明如下:A到B的转换即为:1/A=x/B+y/B的平方+z/B的立方...(x,y,z为任意)

那么,A中的质因子必须全包含在B中,因为B中的质因子可以减少,却不能无故的增加。(比赛的时候写成了A中的质因子必须跟B中的相等)

代码判质因子部分用的的素数测试的模板,因为只有10的12次方,所以不用素数测试的也可以的。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#define time 8
#define call 200
using namespace std;
__int64 x[10000];
__int64 y[10000];
__int64 sum1[10000];
__int64 sum2[10000];
__int64 t,tt;
//============================素数判断====================================//
__int64 mod_mult(__int64 a,__int64 b,__int64 n)//返回 (a*b)%n
{
    a=a%n;
    __int64 res=0;
    while(b)
    {
        if(b&1)
        {
            res+=a;
            if(res>=n) res-=n;
        }
        a=a<<1;
        if(a>=n) a-=n;
        b=b>>1;
    }
    return res;
}
__int64 mod_exp(__int64 a,__int64 b,__int64 n)//返回(a^b)mod n
{
    a=a%n;
    __int64 res=1;
    while(b>=1)
    {
        if(b&1)
            res=mod_mult(res,a,n);
        a=mod_mult(a,a,n);
        b=b>>1;
    }
    return res;
}
bool witness(__int64 a,__int64 n)
{
    __int64 m,x,y;
    int i,j=0;
    m=n-1;
    while(m%2==0)
    {
        m=m>>1;
        j++;
    }
    x=mod_exp(a,m,n);
    for(i=1;i<=j;i++)
    {
        y=mod_exp(x,2,n);
        if(y==1&&x!=1 &&x!=n-1) return true;//二次探测
        x=y;
    }
    if(y!=1)
        return true;
    return false;
}
bool miller_rabin(__int64 n,int s)
{
    if(n==1) return true;
    if(n==2) return false;
    if(n%2==0) return true;
    for(int i=1;i<=s;i++)//s次试探
    {
        __int64 a=rand()%(n-1)+1;
        if(witness(a,n))
            return true;
    }
    return false;//为素数
}
//=======================分解整数因子============================================//
__int64 gcd(__int64 a,__int64 b)
{
    if(b==0) return a;
    return gcd(b,a%b);
}
__int64 pollardRho(__int64  n,int c)
{
    int i=1;
    __int64 x=rand()%n;
    __int64 y=x;
    int k=2;
    while(1)
    {
        i=i+1;
        x=(mod_exp(x,2,n)+c)%n;
        __int64 d=gcd(y-x,n);
        if(1<d&&d<n) return d;
        if(y==x) return n;
        if(i==k)
        {
            y=x;
            k=k*2;
        }
    }
}
void getsmallest1(__int64 n,int c)
{
    if(n==1) return ;
    if(miller_rabin(n,time)==false)//如果为素数
    {
        x[t++]=n;
        return ;
    }
    __int64 val=n;
    while(val==n)
        val=pollardRho(n,c--);
    getsmallest1(val,c);//二分
    getsmallest1(n/val,c);
}
void getsmallest2(__int64 n,int c)
{
    if(n==1) return ;
    if(miller_rabin(n,time)==false)//如果为素数
    {
        y[tt++]=n;
        return ;
    }
    __int64 val=n;
    while(val==n)
        val=pollardRho(n,c--);
    getsmallest2(val,c);//二分
    getsmallest2(n/val,c);
}
int main()
{
    int T;
    long long a,b;
    while(scanf("%d",&T)!=EOF)
    {

        int r=1;
        while(T--)
        {
            memset(sum1,0,sizeof(sum1));
            memset(sum2,0,sizeof(sum2));
            memset(x,0,sizeof(x));
            memset(y,0,sizeof(y));
            cin>>a>>b;
                    t=0;
                    getsmallest1(a,call);
                    tt=0;
                    getsmallest2(b,call);
                    sort(x,x+t);
                    sort(y,y+tt);
                    int g1=0,g2=0;
                    sum1[g1++]=x[0],sum2[g2++]=y[0];
                    for(int i=1;i<t;i++)
                    {
                        if(x[i]!=x[i-1])
                        {

                            sum1[g1++]=x[i];
                        }
                    }
                    for(int i=1;i<tt;i++)
                    {
                        if(y[i]!=y[i-1])
                        {

                            sum2[g2++]=y[i];
                        }
                    }
                    int p1,q1=1;
                    for(int i=0;i<g1;i++)
                    {
                        p1=1;
                        for(int j=0;j<g2;j++)
                        {
                            if(sum1[i]==sum2[j])
                            {
                                p1=0;
                                break;
                            }
                        }
                        if(p1==1)
                        {
                            q1=0;
                            printf("Case #%d: NO\n",r);
                            break;
                        }
                    }
                    if(q1==1)
                     printf("Case #%d: YES\n",r);
            r++;
        }
    }
    return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值