poj2888 Magic Bracelet

时间:2022-09-22 15:29:57

给你一个正n(<10^9)边形和m(<10)种色料,要求给正n边形顶点染色并且规定k组颜色对不能相邻,

输入保证n与mod互质,计数染色总方案数(绕图形中心旋转后相同的方案算一种)对mod取模。

问题的关键在于保证给定的颜色对不相邻,而如果我们用传统的容斥来排除不合法的染色方案在题目给定的n的规模下是不具有可操作性的。

考虑n边形的σi旋转置换,显然有循环:

0 : 0 -> i % n -> 2 *i % n ->... -> 0

1 : 1 -> (i + 1) % n -> (i * 2 + 1) % n ->... -> 1

...

d - 1 : d - 1 -> (i + d - 1) % n -> (i * 2 + d - 1) % n ->... d - 1

即存在d个循环,考虑到每个点的位置是等价的且恰处于一个循环节中,有

各循环节长度相等,其值为l = n / d。

第j + 1个循环中的点p满足 p Ξ j (mod n), 因此若(j + d1 * i ) % n = j,

有d1 * i Ξ 0 (mod n), d1 的最小值为lcm(i, n) / i = n * gcd(i, n)即循环节长度l。

解出d = gcd(i, n)。

显然每个循环节内染色相同,假设第i个循环节染色c(i)。

则n边形染色:c(0) -> c(1) ->...-> c(d - 1) -> c(0) -> c(1) ->....c(d - 1)。

这等价于我们用m种颜色对d 边形染色,同时保证染色合法。

也就是说保证染色:(c(0)c(1)) (c(1)c(2))...(c(d-1)c(0))中成对颜色是合法的。(*)

即便到此用容斥解决也是不可行的,需要将其实现到可快速计算的载体中。

令f(p, q)=

1,若p, q色料可以相邻。

0,其他。

则(*)等价于f(c(0), c(1)) * ... * f(c(d-1), c(0)) = 1。

也就是说每种可行方案为该连乘式贡献1。

考虑布尔矩阵F:

F^n(i,j)表示从i到j路径长度为n的路径总数(这里假设任两点之间距离为1)。

如此所求方案数即∑φ(n / d) * F^d * Inversion(n, mod) % mod (d | n)。

http://poj.org/problem?id=2888

 #include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int mod = ;
const int maxn = ;
int n, m, k, n1;
int prime[], k1;
int p2[], k2;
int cnt[];
int ans; struct Matrix{
int matrix[maxn][maxn];
}B, C; Matrix operator * (Matrix A, Matrix B){
Matrix C;
memset(C.matrix, , sizeof C.matrix);
for(int i = ; i < m; i++){
for(int j = ; j < m; j++){
for(int u = ; u < m; u++){
int p = A.matrix[i][u], q = B.matrix[u][j];
if(p && q) C.matrix[i][j] += p * q;
}
C.matrix[i][j] %= mod;
}
}
return C;
} Matrix operator ^ (Matrix A, int p){
Matrix C;
memset(C.matrix, , sizeof C.matrix);
for(int i = ; i < m; i++) C.matrix[i][i] = ;
while(p){
if(p & ) C = C * A;
p >>= ;
A = A * A;
}
return C;
} int phi(int num){
k2 = ;
for(int i = ; i < k1; i++) if(num % prime[i] == ) num /= prime[i], p2[k2++] = prime[i];
for(int i = ; i < k2; i++) num *= p2[i] - ;
return num % mod;
} int power(int a, int p){
a %= mod;
int ans = ;
while(p){
if(p & ) ans *= a, ans %= mod;
p >>= ;
a *= a;
a %= mod;
}
return ans;
} void dfs(int pos, int num){
if(pos == k1){
C = B ^ num;
int ans1 = ;
for(int i = ; i < m; i++) ans1 += C.matrix[i][i], ans1 %= mod;
ans1 = (ans1 * phi(n / num)) % mod;
ans = (ans + ans1) % mod;
return;
}
int tem = num;
for(int i = ; i <= cnt[pos]; i++){
dfs(pos + , tem);
tem *= prime[pos];
}
} void solve(){
n1 = n;
k1 = ;
memset(cnt, , sizeof cnt);
if(!(n & )){
prime[k1++] = ;
while(!(n & )) n >>= , ++cnt[k1 - ];
}
int mid = (int)sqrt(n);
for(int i = ; i <= mid; i += ){
if(n % i == ){
prime[k1++] = i;
while(n % i == ) n /= i, ++cnt[k1 - ];
mid = (int)sqrt(n);
}
}
if(n != ) prime[k1++] = n, ++cnt[k1 - ];
n = n1;
ans = ;
dfs(, );
ans = ans * power(n, mod - ) % mod;
printf("%d\n", ans);
} int main(){
//freopen("in.txt", "r", stdin);
int T;
scanf("%d", &T);
while(T--){
scanf("%d%d%d", &n, &m, &k);
for(int i = ; i < m; i++) for(int j = ; j < m; j++) B.matrix[i][j] = ;
for(int i = , p, q; i < k; i++){
scanf("%d%d", &p, &q);
--p, --q;
B.matrix[p][q] = B.matrix[q][p] = ;
}
solve();
}
return ;
}

poj2888 Magic Bracelet的更多相关文章

  1. POJ-2888 Magic Bracelet(Burnside引理&plus;矩阵优化&plus;欧拉函数&plus;逆元)

    Burnside引理经典好题呀! 题解参考 https://blog.csdn.net/maxwei_wzj/article/details/73024349#commentBox 这位大佬的. 这题 ...

  2. 【POJ2888】Magic Bracelet Burnside引理&plus;欧拉函数&plus;矩阵乘法

    [POJ2888]Magic Bracelet 题意:一个长度为n的项链,有m种颜色的珠子,有k个限制(a,b)表示颜色为a的珠子和颜色为b的珠子不能相邻,求用m种珠子能串成的项链有多少种.如果一个项 ...

  3. POJ 2888 Magic Bracelet(Burnside引理,矩阵优化)

    Magic Bracelet Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 3731   Accepted: 1227 D ...

  4. poj 2888 Magic Bracelet&lpar;Polya&plus;矩阵快速幂&rpar;

    Magic Bracelet Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 4990   Accepted: 1610 D ...

  5. poj 2888 Magic Bracelet

    经典的有限制条件的Burnside计数+矩阵乘法!!! 对于这种限制条件的情况我们可以通过矩阵连乘得到,先初始化矩阵array[i][j]为1.如果颜色a和颜色b不能涂在相邻的珠子, 那么array[ ...

  6. POJ 2888 Magic Bracelet(burnside引理&plus;矩阵)

    题意:一个长度为n的项链,m种颜色染色每个珠子.一些限制给出有些颜色珠子不能相邻.旋转后相同视为相同.有多少种不同的项链? 思路:这题有点综合,首先,我们对于每个n的因数i,都考虑这个因数i下的不变置 ...

  7. POJ 2888 Magic Bracelet &lbrack;Polya 矩阵乘法&rsqb;

    传送门 题意:竟然扯到哈利波特了.... 和上一题差不多,但颜色数很少,给出不能相邻的颜色对 可以相邻的连边建图矩阵乘法求回路个数就得到$f(i)$了.... 感觉这样的环上有限制问题挺套路的...旋 ...

  8. 解题:POJ 2888 Magic Bracelet

    题面 这题虽然很老了但是挺好的 仍然套Burnside引理(因为有限制你并不能套Polya定理),思路和这个题一样,问题主要是如何求方案. 思路是把放珠子的方案看成一张图,然后就巧妙的变成了一个经典的 ...

  9. poj 2888 Magic Bracelet &lt&semi;polya定理&gt&semi;

    题目:http://poj.org/problem?id=2888 题意:给定n(n <= 10^9)颗珠子,组成一串项链,每颗珠子可以用m种颜色中一种来涂色,如果两种涂色方法通过旋转项链可以得 ...

随机推荐

  1. C&sol;C&plus;&plus; 获取汉字拼音首字母

    #include <stdint.h> #include <stdio.h> #include <ctype.h> #include <string.h&gt ...

  2. java 复习003

    今天主要复习下数据结构的东西 树 自平衡二叉查找树 AVL树(高平衡树)(wiki) 特性:任何节点的两个子树的高度最大差别为一 时间复杂度:查找.插入和删除在平均和最坏情况下都是O(log n) 红 ...

  3. sigaction 用法实例

    sigaction函数的功能是检查或修改与指定信号相关联的处理动作(可同时两种操作). 他是POSIX的信号接口,而signal()是标准C的信号接口(如果程序必须在非POSIX系统上运行,那么就应该 ...

  4. 【Java学习系列】第4课--Java Web相关

    本文地址 分享提纲: 1.概述 2. Jsp基础 2.1 1.概述 1.1)[来源和先导] 本文主要的java web的教程来源JSP是 菜鸟教程JSP 和 天码营Java Web.     主要的先 ...

  5. 『Sklearn』框架自带数据集接口

    自带数据集类型如下: # 自带小型数据集# sklearn.datasets.load_<name># 在线下载数据集# sklearn.datasets.fetch_<name&g ...

  6. PLSQL 触发器

    触发器权限 数据库创建用户时想要在本用户下使用触发器,需要给用户触发器的权限 使用DBA用户执行  GRANT CREATE TRIGGER TO user_name; 如果想在当前用户下创建其他用户 ...

  7. &num;关于 OneVsRestClassifier&lpar;LogisticRegression&lpar;太慢了,要用超过的机器&rpar;

    #关于 OneVsRestClassifier #注意以下代码中,有三个类 from sklearn import datasets X, y = datasets.make_classificati ...

  8. Elasticsearch支持的字段类型

    es支持下列简单的字段类型: String: string Whole number: byte, short, integer, long Floating point: float, double ...

  9. Element &&num;39&semi;plugin&&num;39&semi; cannot have character &lbrack;children&rsqb;&comma; because the type&&num;39&semi;s content type is element-only

    原因是你复制的时候,带了一些特殊符号. 解决方案: 将那一串代码复制到notpad++ 或者文本上面,再复制到你的编译器里面,就可以解决问题了

  10. 代码空间项目 -- alert窗口自定义

    function z_alert(msg){    //创建提示框盒子,设置盒子的css样式    var msgBox=document.createElement("div") ...