• 【POJ】2888 Magic Bracelet


    题意:m种珠子串成由n个珠子构成的环,并且有一些限制,比如第i种与第j种不能相邻,旋转后相同算是同一种方案,求方案数。(m<=10,n<=10^9)

    如果没有限制条件,可以很容易用Burnside定理+容斥得到答案。

    如果只考虑限制,观察发现,m很小,n很大。那么可以通过快速幂得到从第i种到第j种,共有k个珠子的方案数。

    再回到Burnside定理,显然有n种置换,现在问题是如何求每种置换能保持不变的着色方案数:

    【POJ】2154 Color已经推出,第i种置换(即旋转360/n*i度)会有GCD(n,i)种不同的颜色,循环节长度为GCD(n,i)。

    就可以用快速幂得到从第i种回到第i种,共有GCD(n,i)个珠子的方案数。带回Burnside定理+容斥,问题就解决了。

    【POJ】2409 Let it Bead->【POJ】2154 Color->【POJ】2888 Magic Bracelet

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<cmath>
      4 #include<vector>
      5 #define P 9973
      6 #define EPS 1e-8
      7 #define MAXN 12
      8 #define MAXM 32000
      9 using namespace std;
     10 int n, m;
     11 bool p[MAXM];
     12 vector<int> prime;
     13 vector<int> factor;
     14 vector<int> primefactor;
     15 struct Matrix {
     16     int mat[MAXN][MAXN];
     17     void Zero() {
     18         memset(mat, 0, sizeof(mat));
     19     }
     20     void Unit() {
     21         int i;
     22         for (i = 0; i < MAXN; i++)
     23             mat[i][i] = 1;
     24     }
     25 } g;
     26 Matrix operator *(Matrix &a, Matrix &b) {
     27     Matrix tmp;
     28     int i, j, k;
     29     tmp.Zero();
     30     for (k = 0; k < m; k++) {
     31         for (i = 0; i < m; i++) {
     32             if (a.mat[i][k] == 0)
     33                 continue;
     34             for (j = 0; j < m; j++) {
     35                 tmp.mat[i][j] += a.mat[i][k] * b.mat[k][j] % P;
     36                 if (tmp.mat[i][j] >= P)
     37                     tmp.mat[i][j] -= P;
     38             }
     39         }
     40     }
     41     return tmp;
     42 }
     43 Matrix operator ^(Matrix a, int k) {
     44     Matrix tmp;
     45     tmp.Zero();
     46     tmp.Unit();
     47     for (; k; k >>= 1) {
     48         if (k & 1)
     49             tmp = tmp * a;
     50         a = a * a;
     51     }
     52     return tmp;
     53 }
     54 void Init() {
     55     int i, j;
     56     prime.clear();
     57     memset(p, true, sizeof(p));
     58     for (i = 2; i < 180; i++) {
     59         if (p[i]) {
     60             for (j = i * i; j < MAXM; j += i)
     61                 p[j] = false;
     62         }
     63     }
     64     for (i = 2; i < MAXM; i++) {
     65         if (p[i])
     66             prime.push_back(i);
     67     }
     68 }
     69 int ExtGcd(int a, int b, int &x, int &y) {
     70     int t, d;
     71     if (b == 0) {
     72         x = 1;
     73         y = 0;
     74         return a;
     75     }
     76     d = ExtGcd(b, a % b, x, y);
     77     t = x;
     78     x = y;
     79     y = t - a / b * y;
     80     return d;
     81 }
     82 int Invmod(int a, int n) {
     83     int x, y;
     84     ExtGcd(a, n, x, y);
     85     return (x % n + n) % n;
     86 }
     87 void Factor(int x) {
     88     int i, tmp;
     89     factor.clear();
     90     tmp = (int) (sqrt((double) x) + EPS);
     91     for (i = 1; i <= tmp; i++) {
     92         if (x % i == 0) {
     93             factor.push_back(i);
     94             if (i == tmp && i * i == x)
     95                 continue;
     96             factor.push_back(n / i);
     97         }
     98     }
     99 }
    100 int NoChange(int x) {
    101     int i, ans;
    102     Matrix tmp;
    103     tmp = g ^ x;
    104     for (i = ans = 0; i < m; i++) {
    105         ans += tmp.mat[i][i];
    106         if (ans >= P)
    107             ans -= P;
    108     }
    109     return ans;
    110 }
    111 void Prime(int x) {
    112     int i, tmp;
    113     primefactor.clear();
    114     tmp = (int) (sqrt((double) x) + EPS);
    115     for (i = 0; prime[i] <= tmp; i++) {
    116         if (x % prime[i] == 0) {
    117             primefactor.push_back(prime[i]);
    118             while (x % prime[i] == 0)
    119                 x /= prime[i];
    120         }
    121     }
    122     if (x > 1)
    123         primefactor.push_back(x);
    124 }
    125 int Mul(int x, int &k) {
    126     int i, ans;
    127     ans = 1;
    128     for (i = k = 0; x; x >>= 1, i++) {
    129         if (x & 1) {
    130             k++;
    131             ans *= primefactor[i];
    132         }
    133     }
    134     return ans;
    135 }
    136 int Count(int x) {
    137     int i, j, t, ans, tmp;
    138     Prime(x);
    139     ans = 0;
    140     t = (int) primefactor.size();
    141     for (i = 1; i < (1 << t); i++) {
    142         tmp = Mul(i, j);
    143         if (j & 1)
    144             ans += x / tmp;
    145         else
    146             ans -= x / tmp;
    147     }
    148     return (x - ans) % P;
    149 }
    150 int Burnside() {
    151     int i, ans;
    152     Factor(n);
    153     for (i = ans = 0; i < (int) factor.size(); i++) {
    154         ans += Count(n / factor[i]) * NoChange(factor[i]) % P;
    155         if (ans >= P)
    156             ans -= P;
    157     }
    158     return ans * Invmod(n, P) % P;
    159 }
    160 int main() {
    161     int c;
    162     int i, j, k, x, y;
    163     Init();
    164     scanf("%d", &c);
    165     while (c--) {
    166         scanf("%d%d%d", &n, &m, &k);
    167         g.Zero();
    168         for (i = 0; i < m; i++) {
    169             for (j = 0; j < m; j++)
    170                 g.mat[i][j] = 1;
    171         }
    172         while (k--) {
    173             scanf("%d%d", &x, &y);
    174             x--, y--;
    175             g.mat[x][y] = g.mat[y][x] = 0;
    176         }
    177         printf("%d\n", Burnside());
    178     }
    179     return 0;
    180 }
  • 相关阅读:
    信息安全系统设计第一次实验报告
    信息安全系统设计第二次&第四次实验报告
    信息安全系统设计基础第十一周20135334赵阳林
    信息安全系统设计基础第6周学习总结-------20135334赵阳林
    信息安全系统设计基础第五周学习总结------20135334赵阳林
    信息安全系统设计基础第四周学习总结------20135334赵阳林
    信息安全系统设计基础第三周学习总结 ---20135334 赵阳林
    信息安全系统设计基础第二周学习总结
    tcp编程:聊天室中的私聊
    tcp编程:聊天室
  • 原文地址:https://www.cnblogs.com/DrunBee/p/2680185.html
Copyright © 2020-2023  润新知