您的位置:首页 > 其它

hdu 4910 Problem about GCD

2014-08-03 23:15 134 查看
/*
先打表找规律,发现有两种情况
1.当m为满足为某个素数x的k次幂且x不为2时(或者m为偶数且m/2满足情况也是),答案为m-1;
2.其他情况为1;
因为m很大,判定素数要用到muller_rabin随机素数判定。
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <ctime>
using namespace std;
const int S=8;
double eps=1e-8;
long long gcd(long long a,long long b){
return b==0?a:gcd(b,a%b);
}
long long f(long long x){
long long ans=1;
for(int i=2;i<x;i++)if(gcd(i,x)==1)ans=i*ans%x;
return ans;
}
void text(){
for(int i=1;i<=30;i++)
for(int j=1;j<=30;j++)cout<<i<<"*"<<j<<" "<<f(i*j)<<endl;
for(int i=1;i<=10;i++)cout<<(1<<i)<<" "<<f(1<<i)<<endl;
}
long long mult_mod(long long a,long long b,long long c){
a%=c;
b%=c;
long long ret=0;
long long tmp=a;
while(b){
if(b&1){
ret+=tmp;
if(ret>c)ret-=c;
}
tmp<<=1;
if(tmp>c)tmp-=c;
b>>=1;
}
return ret;
}
long long pow_mod(long long a,long long n,long long mod){
long long ret=1;
long long temp=a%mod;
while(n){
if(n&1)ret=mult_mod(ret,temp,mod);
temp=mult_mod(temp,temp,mod);
n>>=1;
}
return ret;
}
bool check(long long a,long long n,long long x,long long t){
long long ret=pow_mod(a,x,n);
long long last=ret;
for(int i=1;i<=t;i++){
ret=mult_mod(ret,ret,n);
if(ret==1&&last!=1&&last!=n-1)return true;
last=ret;
}
if(ret!=1)return true;
else return false;
}
bool muller_rabin(long long n){
if(n<2)return false;
if(n==2)return true;
if((n&1)==0)return false;
long long x=n-1;
long long t=0;
while((x&1)==0){x>>=1;t++;}
srand(time(NULL));
for(int i=0;i<S;i++){
long long a=rand()%(n-1)+1;
if(check(a,n,x,t))return false;
}
return true;
}

long long pow2(long long x,int n){
if(!n)return 1;
long long res=pow2(x,n/2);
res=res*res;
if(n&1)res*=x;
return res;
}

bool ok(long long m){
if(muller_rabin(m))return 1;
for(int i=2;;i++){
long long x=pow(m*1.0,1.0/i)+eps;
// cout<<m<<" "<<x<<" "<<i<<endl;
if(pow2(x,i)==m){
if(muller_rabin(x)){
if(x==2)return 0;
return 1;
}
if(x<=2)return 0;
}
if(x<2)return 0;
}
}
void solve(long long m){
if(ok(m))printf("%I64d\n",m-1);
else if(m%2==0&&ok(m/2))printf("%I64d\n",m-1);
else puts("1");
}
int main()
{
// freopen("in","r",stdin);
// cout<<f(47*47*2)<<endl;
// text();
long long m;
while(scanf("%I64d",&m)>0&&m!=-1){
// cout<<f(m)<<" ";
if(m<=5)printf("%I64d\n",m-1);//特判
else solve(m);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: