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

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

POJ_2888

    自己一开始学polya的时候还是太浮躁了,只是相当于背过了个公式而已,其实根本没建立在理解的基础之上。今天踏下心来又看了一遍黑书,终于能够自己根据burnside引理来推导出polya公式了。

    解决这个题目首先要了解burnside引理的内容,接着就是用dp的方法去具体计算黑书上所谓的C(f)(在置换f下保持不变的着色方案数)了。最后的结果是C(f)的平均值,也就是C(f)/N,由于9973和N互质,所以可以先求N的逆元,进一步就可以得到(C(f)/N)%9973的值了。

    推荐一个此题讲解得非常详细的博客:。

#include
#include
#include
#include
#define MAXD 40010#define MAXM 15#define MOD 9973using namespace std;int N, M, K, prime[MAXD], isprime[MAXD], P, g[MAXM][MAXM], d[MAXD], D;struct Matrix{ int a[MAXM][MAXM]; void init() { memset(a, 0, sizeof(a)); }}unit, mat;void prepare(){ int i, j, k = 40000; P = 0; memset(isprime, -1, sizeof(isprime)); for(i = 2; i <= k; i ++) if(isprime[i]) { prime[P ++] = i; for(j = i * i; j <= k; j += i) isprime[j] = 0; }}int euler(int n){ int i, ans, x; ans = x = n; for(i = 0; i < P && prime[i] * prime[i] <= n; i ++) if(x % prime[i] == 0) { ans = ans / prime[i] * (prime[i] - 1); while(x % prime[i] == 0) x /= prime[i]; } if(x > 1) ans = ans / x * (x - 1); return ans;}void exgcd(int a, int b, int &x, int &y){ if(b == 0) x = 1, y = 0; else exgcd(b, a % b, y, x), y -= x * (a / b);}Matrix multiply(Matrix &x, Matrix &y){ int i, j, k; Matrix z; z.init(); for(i = 0; i < M; i ++) for(k = 0; k < M; k ++) if(x.a[i][k]) { for(j = 0; j < M; j ++) if(y.a[k][j]) z.a[i][j] = (z.a[i][j] + x.a[i][k] * y.a[k][j]) % MOD; } return z;}void init(){ int i, x, y; scanf("%d%d%d", &N, &M, &K); memset(g, -1, sizeof(g)); for(i = 0; i < K; i ++) { scanf("%d%d", &x, &y); -- x, -- y; g[x][y] = g[y][x] = 0; }}void divide(int n){ int i, j; D = 0; for(i = 1; i * i <= n; i ++) if(n % i == 0) { d[D ++] = i; if(n / i != i) d[D ++] = n / i; } sort(d, d + D);}void powmod(Matrix &unit, Matrix &mat, int n){ while(n) { if(n & 1) unit = multiply(mat, unit); n >>= 1; mat = multiply(mat, mat); }}void solve(){ int i, j, x, y, n, ans = 0; divide(N); for(i = 0; i < D; i ++) { n = euler(N / d[i]) % MOD; for(x = 0; x < M; x ++) for(y = 0; y < M; y ++) mat.a[x][y] = -g[x][y]; unit = mat; powmod(unit, mat, d[i] - 1); for(j = 0; j < M; j ++) ans = (ans + n * unit.a[j][j]) % MOD; } exgcd(N, MOD, x, y); x = (x % MOD + MOD) % MOD; ans = (ans * x) % MOD; printf("%d\n", ans);}int main(){ int t; prepare(); scanf("%d", &t); while(t --) { init(); solve(); } return 0;}

转载于:https://www.cnblogs.com/staginner/archive/2012/05/17/2505635.html

你可能感兴趣的文章
ExtJs 分组表格控件----监听
查看>>
Hibernate二级缓存配置
查看>>
LoadRunner常用术语
查看>>
关于jedis2.4以上版本的连接池配置,及工具类
查看>>
记忆讲师石伟华微信公众号2017所有文章汇总(待更新)
查看>>
mechanize (1)
查看>>
FactoryBean
查看>>
Coolite动态加载CheckboxGroup,无法在后台中获取
查看>>
如何在我们项目中利用开源的图表(js chart)
查看>>
nfs服务器工作原理
查看>>
C3P0连接池工具类使用
查看>>
SVN常用命令备注
查看>>
孩子教育
查看>>
解决Cacti监控图像断断续续问题
查看>>
结构体的传参理解成员的存储方式
查看>>
python 进程与线程(理论部分)
查看>>
什么是API
查看>>
Java反射中method.isBridge() 桥接方法
查看>>
[shiro学习笔记]第二节 shiro与web融合实现一个简单的授权认证
查看>>
强名称程序集(strong name assembly)——为程序集赋予强名称
查看>>