Oregon Maple was waiting for Bob When Bob go back home. Oregon Maple asks Bob a problem that as a Positive number N, if there are only four Positive number M makes Gcd(N, M) == M then we called N is a D_num. now, Oregon Maple has some Positive numbers, and if a Positive number N is a D_num , he want to know the four numbers M. But Bob have something to do, so can you help Oregon Maple?
Gcd is Greatest common divisor.
Input
Some cases (case < 100);
Gcd is Greatest common divisor.
Each line have a numeral N(1<=N<10^18) Output For each N, if N is a D_NUM, then output the four M (if M > 1) which makes Gcd(N, M) = M. output must be Small to large, else output “is not a D_num”. Sample Input
6 10 9Sample Output
2 3 6 2 5 10 is not a D_num
题意:给出一个N(1<=N<=10^18),判断N是否恰好有4个因子,如果有,输出三个大于1的因子。反之,输出"is not a D_num"。
数据量有点大,采用Miller_Rabin算法和Pollard_rho算法。
对n=1特判。
将factor数组排序,若有4个因子,可能为以下几种情况:
1. 6=2*3,factor有两个元素,且互不相等。
2. 8=2*2*2,factor有三个元素,且都相等。
其它情况都不存在……
所以可以得到代码
#include <iostream> #include <ctime> #include <algorithm> #define LL long long const int S=20; LL factor[100]; int tot; LL n; using namespace std; LL quickmult(LL a,LL b,LL mod) { a%=mod; b%=mod; LL ans=0; while(b) { if(b&1) { ans+=a; ans%=mod; } b/=2; a=(a+a)%mod; } return ans; } LL quickpow(LL a,LL b,LL mod) { LL ans=1; while(b) { if(b&1) { ans=quickmult(ans,a,mod)%mod; } b/=2; a=quickmult(a,a,mod)%mod; } return ans; /*if(n==1) return a%mod; LL temp=a; LL ret=1; while(b) { if(b&1) ret=quickmult(ret,temp,mod); temp=quickmult(temp,temp,mod); b/=2; } return ret;*/ } bool check(LL a,LL n,LL x,LL T) { LL temp1=quickpow(a,x,n); LL temp2=temp1; while(T--) { temp1=quickmult(temp1,temp1,n); if(temp1==1&&temp2!=1&&temp2!=n-1) return true; temp2=temp1; } if(temp1!=1) return true; return false; } bool Miller_Rabin(LL n) { if(n<2) return false; if(n==2) return true; if((n&1)==0) return false; LL x=n-1; LL t=0; while((x&1)==0) { x>>=1; t++; } for(int i=0; i<S; i++) { LL a=rand()%(n-1)+1; if(check(a,n,x,t)) return false; } return true; } LL gcd(LL a,LL b) { if(a==0) return 1; if(a<0) return gcd(-a,b); while(b) { LL temp=a%b; a=b; b=temp; } return a; } LL Pollard_rho(LL x,LL c) { LL i=1,k=2; LL x0=rand()%x; LL y=x0; while(true) { i++; x0=(quickmult(x0,x0,x)+c)%x; LL d=gcd(y-x0,x); if(d!=1&&d!=x) return d; if(y==x0) return x; if(i==k) { y=x0; k+=k; } } } void findfac(LL n) { if(Miller_Rabin(n)) { factor[tot++]=n; return ; } LL p=n; while(p>=n) { p=Pollard_rho(p,rand()%(n-1)+1); } findfac(p); findfac(n/p); } int main() { while(cin>>n) { if(n==1) { cout<<"is not a D_num"<<endl; continue; } tot=0; findfac(n); sort(factor,factor+tot); if(tot==2) { if(factor[0]!=factor[1]) { cout<<factor[0]<<' '<<factor[1]<<' '<<n<<endl; } else { cout<<"is not a D_num"<<endl; } } else if(tot==3) { if(factor[0]==factor[1]&&factor[1]==factor[2]) { cout<<factor[0]<<' '<<n/factor[0]<<' '<<n<<endl; } else { cout<<"is not a D_num"<<endl; } } else { cout<<"is not a D_num"<<endl; } } return 0; }