给你一个正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引理+矩阵优化+欧拉函数+逆元)

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

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

    [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(Polya+矩阵快速幂)

    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引理+矩阵)

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

  7. POJ 2888 Magic Bracelet [Polya 矩阵乘法]

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

  8. 解题:POJ 2888 Magic Bracelet

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

  9. poj 2888 Magic Bracelet <polya定理>

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

随机推荐

  1. json数据传输有感

    必须把object对象o给JSON.stringify(o) json字符串化 传到后台 前台js的对象某属性如果是Array  那后台就是Long[] idsArray  这种bean的属性对应 然 ...

  2. 0428—Scrum团队成立及《构建之法》第六、七章读后感

    5.Scrum团队成立 5.1 团队名称:喳喳 团队目标:突破渣渣 团队口号:吱吱喳喳 团队照: 5.2 角色分配 产品负责人: 112冯婉莹 Scrum Master:109张鑫相 PM项目经理:1 ...

  3. 内存溢出之Tomcat内存配置

    设置Tomcat启动的初始内存其初始空间(即-Xms)是物理内存的1/64,最大空间(-Xmx)是物理内存的1/4. 可以利用JVM提供的-Xmn -Xms -Xmx等选项可进行设置 三.实例,以下给 ...

  4. html 字体加粗

    <font style="font-weight: bold;">无敌小昆虫</font> <font>无敌小昆虫</font> f ...

  5. 01分数规划poj2728(最优比例生成树)

    Desert King Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 21766   Accepted: 6087 Desc ...

  6. 20145207 《Java程序设计》第10周学习总结

    前言:   最后一篇java博客好激动啊..不过猜猜我在干什么?没错,安虚拟机,唉!紧接着又是一大波信安系统的博客,真开心~好啦边敲博客,边装虚拟机. 教材知识汇总 13.1 网络概述 13.1.1计 ...

  7. maven的pom报plugins却是的解决方法(转)

    maven的pom报plugins却是的解决方法. 引用 Failure to transfer org.apache.maven.plugins:maven-surefire-plugin:pom: ...

  8. 结构体. ->操作符的内涵

    实质上就是结构体成员相对于结构体大变量的偏移地址, 操作符所干的事情就是寻址.是偏移,是偏移,是偏移.偏移后的地址

  9. bzoj4137 [FJOI2015]火星商店问题

    比较容易想到的做法是线段树套字典树,修改操作时在字典树上经过的节点维护一个最近被访问过的时间,这样询问操作只经过满足时间条件的节点,时间复杂度O(NlogN^2)但是因为线段树每个节点都要套个字典树, ...

  10. JSon_零基础_008_将JSon格式的"数组"字符串转换为List集合

    将JSon格式的"数组"字符串转换为List集合. 应用此技术从一个json对象字符串格式中得到一个java对应的对象. JSONObject是一个“name.values”集合, ...