poj 1881:素因子分解+素数テスト
12356 ワード
とても良い入門問題
まず素数であるかどうかをテストし,そうでなければ素因子分解を行い,アルゴリズムの詳細はmiller robinとpollard rhoアルゴリズムをまとめる
ACコード
まず素数であるかどうかをテストし,そうでなければ素因子分解を行い,アルゴリズムの詳細はmiller robinとpollard rhoアルゴリズムをまとめる
ACコード
#include <iostream>
#include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
long long ans;
long long gcd(long long a,long long b)
{
return b?gcd(b,a%b):a;
}
long long random(long long n)
{
return (long long)(rand()%(n-1)+1);
}
long long multi(long long a,long long b,long long m)//a*b%m
{
long long res=0;
while(b>0)
{
if(b&1)
res=(res+a)%m;
b>>=1;
a=(a<<1)%m;
}
return res;
}
long long quickmod(long long a,long long b,long long m) //a^b%m
{
long long res=1;
while(b>0)
{
if(b&1)
res=multi(res,a,m);
b>>=1;
a=multi(a,a,m);
}
return res;
}
int check(long long a,long long n,long long x,long long t)
{
long long res=quickmod(a,x,n);
long long last=res;
for(int i=1;i<=t;i++)
{
res=multi(res,res,n);
if(res==1&&last!=1&&last!=n-1) return 1;
last=res;
}
if(res!=1) return 1;
return 0;
}
int primetest(long long n)
{
if(n<2)return 0;
if(n==2)return 1;
if((n&1)==0) return 0;
long long x=n-1;
long long t=0;
while((x&1)==0){x>>=1;t++;}
for(int i=0;i<20;i++)
{
long long a=random(n);
if(check(a,n,x,t))
return 0;
}
return 1;
}
long long pollardrho(long long n,long long c)
{
long long x,y,d,i,k;
i=1;k=2;
x=random(n);
y=x;
while(1)
{
i++;
x=(multi(x,x,n)+c)%n;
long long tmp=y-x>=0?y-x:x-y;
d=gcd(tmp,n);
if(d>1&&d<n)
return d;
if(y==x)
return n;
if(i==k)
{
y=x;
k+=k;
}
}
}
void findfac(long long n)
{
if(n==1)
return;
if(primetest(n))
{
ans=min(ans,n);
return;
}
long long p=n;
while(p>=n)
p=pollardrho(n,random(n-1));
findfac(p);
findfac(n/p);
}
int main()
{
int t;
long long n;
scanf("%d",&t);
while(t--)
{
scanf("%I64d",&n);
if(primetest(n))
{
puts("Prime");
continue;
}
ans=n;
findfac(n);
printf("%I64d
",ans);
}
return 0;
}