博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
poj2888 Magic Bracelet
阅读量:6516 次
发布时间:2019-06-24

本文共 4083 字,大约阅读时间需要 13 分钟。

给你一个正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)。

 

 

1 #include 
2 #include
3 #include
4 #include
5 using namespace std; 6 const int mod = 9973; 7 const int maxn = 12; 8 int n, m, k, n1; 9 int prime[50], k1; 10 int p2[50], k2; 11 int cnt[50]; 12 int ans; 13 14 struct Matrix{ 15 int matrix[maxn][maxn]; 16 }B, C; 17 18 Matrix operator * (Matrix A, Matrix B){ 19 Matrix C; 20 memset(C.matrix, 0, sizeof C.matrix); 21 for(int i = 0; i < m; i++){ 22 for(int j = 0; j < m; j++){ 23 for(int u = 0; u < m; u++){ 24 int p = A.matrix[i][u], q = B.matrix[u][j]; 25 if(p && q) C.matrix[i][j] += p * q; 26 } 27 C.matrix[i][j] %= mod; 28 } 29 } 30 return C; 31 } 32 33 Matrix operator ^ (Matrix A, int p){ 34 Matrix C; 35 memset(C.matrix, 0, sizeof C.matrix); 36 for(int i = 0; i < m; i++) C.matrix[i][i] = 1; 37 while(p){ 38 if(p & 1) C = C * A; 39 p >>= 1; 40 A = A * A; 41 } 42 return C; 43 } 44 45 int phi(int num){ 46 k2 = 0; 47 for(int i = 0; i < k1; i++) if(num % prime[i] == 0) num /= prime[i], p2[k2++] = prime[i]; 48 for(int i = 0; i < k2; i++) num *= p2[i] - 1; 49 return num % mod; 50 } 51 52 int power(int a, int p){ 53 a %= mod; 54 int ans = 1; 55 while(p){ 56 if(p & 1) ans *= a, ans %= mod; 57 p >>= 1; 58 a *= a; 59 a %= mod; 60 } 61 return ans; 62 } 63 64 void dfs(int pos, int num){ 65 if(pos == k1){ 66 C = B ^ num; 67 int ans1 = 0; 68 for(int i = 0; i < m; i++) ans1 += C.matrix[i][i], ans1 %= mod; 69 ans1 = (ans1 * phi(n / num)) % mod; 70 ans = (ans + ans1) % mod; 71 return; 72 } 73 int tem = num; 74 for(int i = 0; i <= cnt[pos]; i++){ 75 dfs(pos + 1, tem); 76 tem *= prime[pos]; 77 } 78 } 79 80 void solve(){ 81 n1 = n; 82 k1 = 0; 83 memset(cnt, 0, sizeof cnt); 84 if(!(n & 1)){ 85 prime[k1++] = 2; 86 while(!(n & 1)) n >>= 1, ++cnt[k1 - 1]; 87 } 88 int mid = (int)sqrt(n); 89 for(int i = 3; i <= mid; i += 2){ 90 if(n % i == 0){ 91 prime[k1++] = i; 92 while(n % i == 0) n /= i, ++cnt[k1 - 1]; 93 mid = (int)sqrt(n); 94 } 95 } 96 if(n != 1) prime[k1++] = n, ++cnt[k1 - 1]; 97 n = n1; 98 ans = 0; 99 dfs(0, 1);100 ans = ans * power(n, mod - 2) % mod;101 printf("%d\n", ans);102 }103 104 int main(){105 //freopen("in.txt", "r", stdin);106 int T;107 scanf("%d", &T);108 while(T--){109 scanf("%d%d%d", &n, &m, &k);110 for(int i = 0; i < m; i++) for(int j = 0; j < m; j++) B.matrix[i][j] = 1;111 for(int i = 0, p, q; i < k; i++){112 scanf("%d%d", &p, &q);113 --p, --q;114 B.matrix[p][q] = B.matrix[q][p] = 0;115 }116 solve();117 }118 return 0;119 }
View Code

 

转载于:https://www.cnblogs.com/astoninfer/p/4823140.html

你可能感兴趣的文章
《Java EE 7精粹》—— 2.5 非阻塞I/O
查看>>
《R数据可视化手册》——1.1 安装包
查看>>
spring-aop
查看>>
android RecycleView Adapter简单封装
查看>>
Dart的数据库操作
查看>>
Codeforces 591 B Rebranding【Codeforces Round #327 (Div. 2)】
查看>>
命名难,难于上青天
查看>>
APUE读书笔记-05标准输入输出库(7)
查看>>
23 第一周作业
查看>>
DNS解析偶尔延迟
查看>>
iOS打电话,发短信,发邮件,打开网址
查看>>
Java数据结构与算法(六) 希尔排序
查看>>
canvas学习笔记
查看>>
CSS3秘笈第三版涵盖HTML5学习笔记9~12章
查看>>
《Spring1之第十次站立会议》
查看>>
Unity Shader 噪声消融特效 - 剑灵死亡特效
查看>>
添加一条信息到列表,如果重复就替换,
查看>>
C#基础第五天
查看>>
uva 12325 枚举暴力 b
查看>>
多线程问题(JVM重排序)
查看>>