hdu 4910 Problem about GCD

来源:互联网 发布:淘宝客服有5%的提成吗? 编辑:程序博客网 时间:2024/06/06 08:41

Problem about GCD

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


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
12345-1
 

Sample Output
01234
 

Source
BestCoder Round #3
 

暴力打表,然后找规律,表如下:

1 0
2 1
3 2
4 3
5 4
6 5
7 6
8 1
9 8
10 9
11 10
12 1
13 12
14 13
15 1
16 1
17 16
18 17
19 18
20 1
21 1
22 21
23 22
24 1
25 24
26 25
27 26
28 1
29 28
30 1
31 30
32 1
33 1
34 33
35 1
36 1
37 36
38 37
39 1
40 1
41 40
42 1
43 42
44 1
45 1
46 45
47 46
48 1
49 48
50 49
51 1
52 1
53 52
54 53
55 1
56 1
57 1
58 57
59 58
60 1
61 60
62 61
63 1
64 1
65 1
66 1
67 66
68 1
69 1
70 1
71 70
72 1
73 72
74 73
75 1
76 1
77 1
78 1
79 78
80 1
81 80
82 81
83 82
84 1
85 1
86 85
87 1
88 1
89 88
90 1
91 1
92 1
93 1
94 93
95 1
96 1
97 96
98 97
99 1
100 1
101 100
102 1
103 102
104 1
105 1
106 105
107 106
108 1
109 108
110 1
111 1
112 1
113 112
114 1
115 1
116 1
117 1
118 117
119 1
120 1
121 120
122 121
123 1
124 1
125 124
126 1
127 126
128 1
129 1
130 1
131 130
132 1
133 1
134 133
135 1
136 1
137 136
138 1
139 138
140 1
141 1
142 141
143 1
144 1

我们发现,答案不是n-1就是1.

1的情况:4的倍数(4除外);奇数质因数多于1个的;偶数除以2后质因数多于1个的

n-1的情况: 1,质数;n = p^x(n为奇数,比如27,9,25, 125,3)因 x 可以为1所以质数也在这个集合中, 或 n = 2*p^x(n为偶数,比如142(2*71^1),54(2*3*^3),其中p为质数。


找到规律后,就要尝试。刚开始用Miller_Rabin判素数 + pollard_rho质因数分解结果TLE了,可能是姿势不对。后来换了一种分解法就过了。详见代码

#include <iostream>#include <algorithm>#include <cstdio>#include <string>#include <cstring>#include <cmath>#include <vector>#include <list>#include <map>#include <set>#include <deque>#include <queue>#include <stack>#include <bitset>#include <functional>#include <sstream>#include <iomanip>#include <cmath>#include <cstdlib>#include <ctime>//#pragma comment(linker, "/STACK:102400000,102400000")typedef long long ll;#define INF 1e9#define MAXN 21const int maxn = 1000005;//#define mod 1000000007#define eps 1e-7#define pi 3.1415926535897932384626433#define rep(i,n) for(int i=0;i<n;i++)#define rep1(i,n) for(int i=1;i<=n;i++)#define scan(n) scanf("%d",&n)#define scanll(n) scanf("%I64d",&n)#define scan2(n,m) scanf("%d%d",&n,&m)#define scans(s) scanf("%s",s);#define ini(a) memset(a,0,sizeof(a))#define out(n) printf("%d\n",n)//ll gcd(ll a,ll b) { return b==0?a:gcd(b,a%b);}using namespace std;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1//****************************************************************// Miller_Rabin 算法进行素数测试//速度快,而且可以判断 <2^63的数//****************************************************************const int S=20;//随机算法判定次数,S越大,判错概率越小int prime[maxn];int c;bool vis[maxn];void init(){c = 0;ini(vis);for(int i = 2;i <= 1000000; i++){if(vis[i]) continue;prime[c++] = i;for(int j = i + i;j <= 1000000; j += i) vis[j] = true;}}//计算 (a*b)%c.   a,b都是long long的数,直接相乘可能溢出的//  a,b,c <2^63long long mult_mod(long long a,long long b,long long c){    a%=c;    b%=c;    long long ret=0;    while(b)    {        if(b&1){ret+=a;ret%=c;}        a<<=1;        if(a>=c)a%=c;        b>>=1;    }    return ret;}long long pow_mod(long long x,long long n,long long mod)//x^n%c{    if(n==1)return x%mod;    x%=mod;    long long tmp=x;    long long ret=1;    while(n)    {        if(n&1) ret=mult_mod(ret,tmp,mod);        tmp=mult_mod(tmp,tmp,mod);        n>>=1;    }    return ret;}//以a为基,n-1=x*2^t      a^(n-1)=1(mod n)  验证n是不是合数//一定是合数返回true,不一定返回falsebool 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;    return false;}// Miller_Rabin()算法素数判定//是素数返回true.(可能是伪素数,但概率极小)//合数返回false;bool Miller_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++;}    for(int i = 0;i < S; i++)    {        long long a=rand()%(n-1)+1;//rand()需要stdlib.h头文件        if(check(a,n,x,t))            return false;//合数    }    return true;}bool squre(ll n){ll m = sqrt(n * 1.0);return m * m == n || (m-1) * (m-1) == n || (m+1) * (m+1) == n;}bool solve(ll n){if(Miller_Rabin(n)) return true; //是素数直接返回int times = 0;ll m = n;for(int i = 0;i < c; i++){if(m % prime[i] == 0){times++; //记录不同素因子数,大于2直接返回if(times >= 2) return false;while(m % prime[i] == 0){ m /= prime[i];}}if(m == 1) return true; //说明能被一个质数完全分解}if(m != n) return false; //当m != n时,但m != 1,说明n至少有一个小于1e6和一个大于1e6的质因数,直接返回if(squre(n)) return true; //若10^6以内的质因数都不能分解,就判断是不是完全平方数,因为10^18最多  //容许两个大于10^6的数相乘return false;}ll n;int main(){#ifndef ONLINE_JUDGEfreopen("in.txt","r",stdin);// freopen("out.txt","w",stdout);#endif  init();//cout<<prime[c-1]<<endl;while(~scanf("%I64d",&n)){if(n == -1) break;if(n == 1){puts("0");continue;}if(n != 4 && n % 4 == 0){puts("1");continue;}ll m = n;if(m % 2 == 0) m /= 2;if(!solve(m))puts("1");elseprintf("%I64d\n",n-1);}return 0;}



0 0
原创粉丝点击