题意:n个珠子的环,之多着n种颜色,考虑旋转,不考虑翻转。问模P的方案数。

运用Burnside定理,有n个置换,每个置换使得着色不变的着色个数有GCD(n,i)个。

GCD(n,i)个的原因:【POJ】2409 Let it Bead

由于n达到十亿,显然不能枚举。但是可以发现,GCD(n,i)即n约数的个数很少。

问题转化为1~n有多少个数,使得GCD(n,i)=k。其中k是n的约数。这个问题等价于与n/k互质的个数有多少,那么容斥就能搞定。

由于有模P,Burnside定理最后要除以n,但是n与P不一定互质,可能没有逆元。观察到分子,不妨先都除以n,就避免了这个问题。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cmath>
  4 #include<vector>
  5 #define EPS 1e-8
  6 #define MAXN 32000
  7 using namespace std;
  8 vector<int> fac;
  9 vector<int> g;
 10 vector<int> prime;
 11 int P;
 12 bool p[MAXN];
 13 void Init() {
 14     int i, j;
 15     memset(p, true, sizeof(p));
 16     for (i = 2; i < 180; i++) {
 17         if (p[i]) {
 18             for (j = i * i; j < MAXN; j += i)
 19                 p[j] = false;
 20         }
 21     }
 22     prime.clear();
 23     for (i = 2; i < MAXN; i++) {
 24         if (p[i])
 25             prime.push_back(i);
 26     }
 27 }
 28 void Factor(int n) {
 29     int i, tmp;
 30     fac.clear();
 31     tmp = (int) (sqrt((double) n) + EPS);
 32     for (i = 1; i <= tmp; i++) {
 33         if (n % i == 0) {
 34             fac.push_back(i);
 35             if (i == tmp && i * i == n)
 36                 continue;
 37             fac.push_back(n / i);
 38         }
 39     }
 40 }
 41 int PowMod(int a, int b, int c) {
 42     int res;
 43     a %= c;
 44     for (res = 1; b; b >>= 1) {
 45         if (b & 1) {
 46             res *= a;
 47             res %= c;
 48         }
 49         a *= a;
 50         a %= c;
 51     }
 52     return res;
 53 }
 54 void Prime(int x) {
 55     int i, tmp;
 56     g.clear();
 57     tmp = (int) (sqrt((double) x) + EPS);
 58     for (i = 0; prime[i] <= tmp; i++) {
 59         if (x % prime[i] == 0) {
 60             g.push_back(prime[i]);
 61             while (x % prime[i] == 0)
 62                 x /= prime[i];
 63         }
 64     }
 65     if (x > 1)
 66         g.push_back(x);
 67 }
 68 int Mul(int x, int &k) {
 69     int i, ans = 1;
 70     for (i = k = 0; x; x >>= 1, i++) {
 71         if (x & 1) {
 72             ans *= g[i];
 73             k++;
 74         }
 75     }
 76     return ans;
 77 }
 78 int Count(int x) {
 79     int i, j, t, tmp, ans;
 80     Prime(x);
 81     ans = 0;
 82     t = (int) g.size();
 83     for (i = 1; i < (1 << t); i++) {
 84         tmp = Mul(i, j);
 85         if (j & 1)
 86             ans += x / tmp;
 87         else
 88             ans -= x / tmp;
 89     }
 90     return (x - ans) % P;
 91 }
 92 int main() {
 93     int c;
 94     int n, ans, i;
 95     Init();
 96     scanf("%d", &c);
 97     while (c--) {
 98         scanf("%d%d", &n, &P);
 99         Factor(n);
100         ans = 0;
101         for (i = 0; i < (int) fac.size(); i++) {
102             ans += PowMod(n, fac[i] - 1, P) * Count(n / fac[i]);
103             ans %= P;
104         }
105         printf("%d\n", ans);
106     }
107     return 0;
108 }
posted on 2012-09-10 15:31  DrunBee  阅读(1428)  评论(0编辑  收藏  举报