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 }

 

posted @ 2013-01-29 20:45  ACSeed  Views(202)  Comments(0)    收藏  举报