首页 > 代码库 > HDU 4910 Problem about GCD

HDU 4910 Problem about GCD

Problem about GCD

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 470    Accepted Submission(s): 77


Problem Description
Given integer m. Find multiplication of all 1<=a<=m such gcd(a, m)=1 (coprime with m) modulo m.
 

 

Input
Input contains multiple tests, one test per line.
Last line contains -1, it should be skipped.

[Technical Specification]
m <= 10^18
 

 

Output
For each test please output result. One case per line. Less than 160 test cases.
 

 

Sample Input
1
2
3
4
5
-1
 
Sample Output
0
1
2
3
4
Source
BestCoder Round #3
 
打表找规律:
数字n 如果由 x^k组成  或者 2*y^k 组成(x,y不等于2了,k为1,2,3,....) 则结果为n-1;
否则为1.
 
思路:
1.特判%4的情况。
2.m = n  , 如果m为偶数先除2 。
3.如果m本身就是素数 m = m^1 ,那就是n-1了。
4.如果m由两个素数组成 m = x*x ,x是素数. 也简单,开平方,然后判断是不是素数。
5.如果m由多个素数组成 m = x^k,那么这个素数一定在10^6里面出现。
  至少为3次吧。
代码很挫。
  1 #include<iostream>  2 #include<stdio.h>  3 #include<cstring>  4 #include<stdlib.h>  5 #include<time.h>  6 #include<math.h>  7 using namespace std;  8 typedef __int64 LL;  9 const int maxn = 1e6+1; 10 int prime[maxn],len; 11 bool s[maxn]; 12  13 void init() 14 { 15     int i,j; 16     len = 0; 17     memset(s,true,sizeof(s)); 18     s[1] = false; 19     for(i=2;i<maxn;i++) 20     { 21         if(s[i] == false) continue; 22         prime[++len] = i; 23         for(j=i*2;j<maxn;j=j+i) 24             s[j] = false; 25     } 26 } 27 //**************************************************************** 28 // Miller_Rabin 算法进行素数测试 29 //速度快,而且可以判断 <2^63的数 30 //**************************************************************** 31 const int S=20;//随机算法判定次数,S越大,判错概率越小 32 LL mult_mod(LL a,LL b,LL mod) //(a*b)%c a,b,c<2^63 33 { 34     a%=mod; 35     b%=mod; 36     LL ans=0; 37     while(b) 38     { 39         if(b&1) 40         { 41             ans=ans+a; 42             if(ans>=mod) 43             ans=ans-mod; 44         } 45         a=a<<1; 46         if(a>=mod) a=a-mod; 47         b=b>>1; 48     } 49     return ans; 50 } 51 LL pow_mod(LL a,LL b,LL mod) // a^b%mod 52 { 53     LL ans=1; 54     a=a%mod; 55     while(b) 56     { 57         if(b&1) 58         { 59             ans=mult_mod(ans,a,mod); 60         } 61         a=mult_mod(a,a,mod); 62         b=b>>1; 63     } 64     return ans; 65 } 66  67 //以a为基,n-1=x*2^t      a^(n-1)=1(mod n)  验证n是不是合数 68 //一定是合数返回true,不一定返回false 69  70 bool check(LL a,LL n,LL x,LL t) 71 { 72     LL ret=pow_mod(a,x,n); 73     LL last=ret; 74     for(int i=1;i<=t;i++) 75     { 76         ret=mult_mod(ret,ret,n); 77         if(ret==1 && last!=1 && last!=n-1) return true;//合数 78         last=ret; 79     } 80     if(ret!=1) return true; 81     else return false; 82 } 83  84 // Miller_Rabin()算法素数判定 85 //是素数返回true.(可能是伪素数,但概率极小) 86 //合数返回false; 87  88 bool Miller_Rabin(LL n) 89 { 90     if(n<2)return false; 91     if(n==2) return true; 92     if( (n&1)==0) return false;//偶数 93     LL x=n-1; 94     LL t=0; 95     while( (x&1)==0 ) { x>>=1;t++;} 96     for(int i=0;i<S;i++) 97     { 98         LL a=rand()%(n-1)+1;//rand()需要stdlib.h头文件 99         if(check(a,n,x,t))100         return false;//合数101     }102     return true;103 }104 bool Euler(LL n)105 {106     LL i , knum = 0;107     for(i=1;prime[i]<=n&&i<=len;i++)108     {109         if(n%prime[i]==0)110         {111             while(n%prime[i]==0)112                 n=n/prime[i];113             knum++;114         }115         if(knum>=2) break;116     }117     if(knum == 1 && n==1) return true;118     /**此处为n == 1 不是n == 0**/119     return false;120 }121 void solve(LL n,LL m)122 {123     if( (m<=1000000 && s[m] == true) || Miller_Rabin(m) == true)124     {125         printf("%I64d\n",n-1);126         return;127     }128     LL k = (LL)sqrt(m*1.0);129     if(k * k == m && Miller_Rabin(k) == true)130     {131         printf("%I64d\n",n-1);132         return;133     }134     if(Euler(m)==true)135     {136         printf("%I64d\n",n-1);137         return;138     }139     printf("1\n");140 }141 int main()142 {143     init();144     LL n , m;145     while(scanf("%I64d",&n)>0)146     {147         if(n==-1) break;148         if(n<=5){149             printf("%I64d\n",n-1);150             continue;151         }152         m = n;153         if( (m&1) == 0)154         {155             m = m /2;156             if((m&1)==0)157             {158                 printf("1\n");159                 continue;160             }161         }162         solve(n,m);163     }164     return 0;165 }