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 }

HDU 4910 Problem about GCD,布布扣,bubuko.com

时间: 2024-11-16 16:43:47

HDU 4910 Problem about GCD的相关文章

hdu 4910 Problem about GCD(数论)

题目连接:hdu 4910 Problem about GCD 题目大意:给定M,判断所有小于M并且和M互质的数的积取模M的值. 解题思路:有个数论的结论,若为偶数,M=M/2. 可以写成M=pk,即只有一种质因子时,答案为M-1,否则为1.特殊情况为4的倍数,不包括4. 首先用1e6以内的素数去试除,如果都不可以为p,那么对大于1e6的情况判断一下是否为素数,是素数也可以(k=1),否则开方计算,因为M最大为1e18,不可能包含3个大于1e6的质因子. #include <cstdio> #

HDU 4910 Problem about GCD(米勒拉宾)

HDU 4910 Problem about GCD 题目链接 题意:给定一个数字,求出1 - n之间与他互质的数的乘积mod n 思路:看了网上别人找出来的规律,原文链接 然后由于这题的n很大,也没法直接判定,可以这样搞,先去试10^6以内的素数,判断可不可以,如果不行,再利用米勒拉宾判下是否是素数,如果不是的话,把这个数字开根在平方,判断是不是完全平方数,这样做的原因是数字最大10^18,如果没有10^6以内的质因子,又不是质数的话,那么他最多只能包含2个质因子了,那么如果他不是一个完全平方

HDU 4910 HDOJ Problem about GCD BestCoder #3 第四题

首先 m = 1 时 ans = 0对于 m > 1 的 情况 由于 1 到 m-1 中所有和m互质的数字,在 对m的乘法取模 运算上形成了群 ai = ( 1<=a<m && gcd(a,m) == 1 ) 所以 对于 a 必然存在b = a^(-1) = inv(a) 使得 a * b = 1 (mod m) 这里存在两种情况 a != b 那么最后的连乘式中a b均出现一次,相乘得1 a == b 那么最后的连乘式中只出现一个a 实际上所有 a = inv(a) 的

hdu 5869 区间不同GCD个数(树状数组)

Different GCD Subarray Query Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 221    Accepted Submission(s): 58 Problem Description This is a simple problem. The teacher gives Bob a list of probl

HDU 4983 Goffi and GCD(数论)

HDU 4983 Goffi and GCD 思路:数论题,如果k为2和n为1,那么只可能1种,其他的k > 2就是0种,那么其实只要考虑k = 1的情况了,k = 1的时候,枚举n的因子,然后等于求该因子满足的个数,那么gcd(x, n) = 该因子的个数为phi(n / 该因子),然后再利用乘法原理计算即可 代码: #include <cstdio> #include <cstring> #include <cmath> typedef long long l

hdu 4983 Goffi and GCD(数论)

题目链接:hdu 4983 Goffi and GCD 题目大意:求有多少对元组满足题目中的公式. 解题思路: n = 1或者k=2时:答案为1 k > 2时:答案为0(n≠1) k = 1时:需要计算,枚举n的因子,令因子k=gcd(n?a,n, 那么另一边的gcd(n?b,n)=nk才能满足相乘等n,满足k=gcd(n?a,n)的a的个数即为?(n/s),欧拉有o(n ̄ ̄√的算法 #include <cstdio> #include <cstring> #include

HDU 2256 Problem of Precision (矩阵快速幂)

HDU 2256 Problem of Precision (矩阵快速幂) ACM 题目地址:HDU 2256 Problem of Precision 题意: 给出一个式子,求值. 分析: 推起来最后那步会比较难想. 具体过程见: 表示共轭只听说过复数的和图的... 这构题痕迹好明显... 跟基友开玩笑说:如果遇到这种题,推到Xn+Yn*sqrt(6)这步时,打表最多只能打到10就爆int了,这是输出正解和Xn,说不定眼神好能发现ans = Xn * 2 - 1呢.= =... 代码: /*

hdu 2504 又见Gcd

有时候觉得自己也挺天才滴~O(∩_∩)O~,小小鼓励下.(虽然是道大水题吧....囧) 1 #include<stdio.h> 2 int Gcd(int m,int n) 3 { 4 return m==0?n:Gcd(n%m,m); 5 } 6 int main() 7 { 8 int n; 9 scanf("%d",&n); 10 while(n--) 11 { 12 int a,b,i; 13 scanf("%d%d",&a,&a

hdu String Problem(最小表示法入门题)

hdu 3374 String Problem 最小表示法 view code#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <map> #include <string> using namespace std; const int N = 10010; int n; char s[105]; map<