10692 - Huge Mods
题目要求a0^a1^a2^a3^a4..., 我们先来考虑(a^p)%m:
1)如果a与m互质, 则a属于Z*m, 则由a生成的群是Z*m的子群, 设a的阶为T, Z*m的大小为S,由Lagrange定理知,T | S;T是a的生成群的循环节, 可知S也是a的生成群的循环节,所以有:
(a^p) % m == (a^(p % phi(m))) % m;
2)如果a与m不互质,那我们要把他们转化为互质的情形,由余数的定义有:
(a^p) % m = a^p - x * m = c
要使a和m互质, 必须把m中a的因子除干净, 假设这些因子的乘积为k, m除完因子之后的值为m',则上面的式子变成了:
(a^p) / k - x * m' = c / k;
问题变成了求:
((a^p) / k )% m';
求出来的结果是 c / k, 所以最后还要乘上一个k.
View Code
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cmath> 5 #include<vector> 6 #include<string> 7 #include<sstream> 8 #include<cstring> 9 using namespace std; 10 11 const int maxn = 1000 + 10; 12 13 int size; 14 int a[maxn]; 15 int fac[maxn][2], flen; 16 17 int prime[maxn], plen; 18 bool vis[maxn]; 19 void mklist() { 20 memset(vis, false, sizeof(vis)); 21 plen = 0; 22 for(int i = 2; i * i < maxn; ++i) { 23 if(!vis[i]) { 24 for(int j = i; j * i < maxn; ++j) vis[i * j] = true; 25 } 26 } 27 for(int i = 2; i < maxn; ++i) if(!vis[i]) prime[plen++] = i; 28 } 29 30 int pow_mod(int a, int p, int m) { 31 int ans = 1; 32 a %= m; 33 for(; p; p >>= 1) { 34 if(p & 1) ans = (ans * a) % m; 35 a = (a * a) % m; 36 } 37 return ans; 38 } 39 40 void gcd(int a, int b, int &d, int& x, int &y) { 41 if(!b) { 42 d = a; x = 1; y = 0; 43 } else { 44 gcd(b, a % b, d, y, x); 45 y -= (a / b) * x; 46 } 47 } 48 49 void split(int n) { 50 flen = 0; 51 for(int i = 0; i < plen && prime[i] <= n; ++i) { 52 if(n % prime[i] == 0) { 53 fac[flen][0] = prime[i]; 54 fac[flen][1] = 0; 55 while(n % prime[i] == i) { 56 n /= prime[i]; 57 fac[flen][1]++; 58 } 59 ++flen; 60 } 61 } 62 } 63 64 int phi(int n) { 65 int ans = n; 66 int m = (int)sqrt(n + 0.5); 67 for(int i = 2; i <= m; ++i) { 68 if(n % i == 0) { 69 ans = ans / i * (i - 1); 70 while(n % i == 0) n /= i; 71 } 72 } 73 if(n > 1) ans = ans / n * (n - 1); 74 return ans; 75 } 76 int inv(int a, int n) { 77 int d, x, y; 78 gcd(a, n, d, x, y); 79 return d == 1 ? (x % n + n) % n : -1; 80 } 81 82 int huge_mod(int a0, int *a, int size, int mod) { 83 if(mod == 1) return 0; 84 if(a0 % mod == 0) return 0; 85 if(size == 1) return pow_mod(a0, a[0], mod); 86 int d, x, y; 87 gcd(a0, mod, d, x, y); 88 if(d == 1) { 89 int ans = huge_mod(a[0], a + 1, size - 1, phi(mod)); 90 ans = pow_mod(a0, ans, mod); 91 return ans; 92 } else { 93 split(a0); 94 int mm = mod; 95 for(int i = 0; i < flen; ++i) { 96 while(mm % fac[i][0] == 0) mm /= fac[i][0]; 97 } 98 int ans = huge_mod(a0, a, size, mm); 99 int x = inv(mod / mm, mm); 100 ans = (((ans * (mod / mm)) % mod) * x) % mod; 101 return ans; 102 } 103 } 104 105 int main() { 106 string line; 107 int k = 0; 108 mklist(); 109 int n, m; 110 while(cin >> m) { 111 cin >> n; 112 bool flg = false; 113 size = 0; 114 for(int i = 0; i < n; ++i) { 115 cin >> a[i]; 116 if(flg) continue; 117 if(a[i] > 1) ++size; 118 else flg = true; 119 } 120 121 int ans ; 122 if(size == 0) ans = 1; 123 else if(size == 1) ans = a[0] % m; 124 else ans = huge_mod(a[0], a + 1, size - 1, m); 125 cout << "Case #" << ++k << ": " << ans % m << endl; 126 } 127 return 0; 128 }


浙公网安备 33010602011771号