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
 
打表找规律:
数字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 }

 

posted @ 2014-08-08 22:26  芷水  阅读(525)  评论(0编辑  收藏  举报