首页 > 代码库 > 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
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 }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。