参考知识链接

 

关于枚举旋转置换:

  前两题都是枚举了 n 种旋转, 但这个可以优化到\(O(\sqrt{n})\) (这个其实是基本操作). 考虑到每个循环节的长度都是 n 的因数, 所以可以枚举 n 的因数, 再乘以这个因数的贡献, 即被计算了几次, 对于一个数 a, 如果gcd(a, n) == d, 那么 a 就对 d 产生了 1 次贡献, 而一共有\(\varphi{(n/d)}\)个这样的数.

 

POJ 2409

题意: 有一串 s 个珠子的项链, 每个珠子的颜色有 c 种, 经过旋转和轴对称变换后相等的项链是视为相同的, 问有多少种项链.

思路: 旋转次数有[0, s - 1] 共 s 种, 对称操作分奇偶讨论, 不过都是 n 种, 然后用 Pólya 定理计算结果.

view code
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
#define ll long long int c, s; inline ll ksm(ll a, ll n) {
ll r = 1;
while (n) {
if (n & 1) r = r * a;
a = a * a;
n >>= 1;
}
return r;
} int gcd(int x, int y) {
if (y == 0) return x;
return gcd(y, x % y);
} int main() {
while (scanf("%d %d", &c, &s) != EOF && c) {
ll res = ksm((ll)c, (ll)s); // 0
for (int i = 1; i < s; i++) {
res += ksm((ll)c, (ll)gcd(i, s));
}
if (s & 1)
res += s * ksm((ll)c, (s + 1) / 2);
else
res += (c + 1) * s / 2 * ksm((ll)c, s / 2);
printf("%lld\n", res / 2 / s);
}
}

 

AOJ 2164

题意: 有两国的大使共 N 人要坐在一个圆周上开会, 不能有连续的 k 个同国的人坐在一起, 问有多少种坐法. N ≤ 1000, k ≤ 1000.

思路: 这题难点在于确定了循环节长度之后, 有多少种合法的坐法. 对于一个循环节, 不妨考虑开头为A, 根据对称性最后把答案乘 2 就是总的情况数. 定义dp_a[i][j], dp_b[i][j]为总长为 i, 结尾有 j 个 A/B, 中间没有连续 k 个同国 (但不考虑首尾相连超过 k, 不然状态数有\(N^3\)种) 的情况数. 需要计算一个合法的循环节时, 分类讨论结尾是A/B: 结尾是A时, 考虑除去开头和结尾后还剩的串长(保证不为0, 否则会重复计数), 此时剩下的串开头和结尾都是B, 它的数量和同长度的开头结尾都是A的串相同! 再乘以出现该剩余串长的次数; 结尾是 B 时, 首尾相连必不连续, dp_b的前缀和即是所求. 最后还有一个特意省略的情况: 全为A, 注意此时不能简单地认为首尾数相加不大于 k 即可, 因为此时整个环都是 A 应该比较 n 与 k.

view code
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inc(i, l, r) for (int i = l; i <= r; i++) const int maxn = 1005;
const int mod = 1000003; int n, k;
int dp_a[maxn][maxn], dp_b[maxn][maxn]; //一定以a开头,总长为i, 结尾是j个a/b
int sum_a[maxn], sum_b[maxn]; inline ll ksm(ll a, ll n) {
ll r = 1;
while (n) {
if (n & 1) r = r * a % mod;
a = a * a % mod;
n >>= 1;
}
return r;
} int main() {
while (cin >> n >> k && n) {
memset(dp_a, 0, sizeof(dp_a));
memset(dp_b, 0, sizeof(dp_b));
dp_a[1][1] = 1;
inc(i, 1, n - 1) {
inc(j, 1, min(i, k)) {
if (j + 1 <= k)
dp_a[i + 1][j + 1] =
(dp_a[i + 1][j + 1] + dp_a[i][j]) % mod;
dp_b[i + 1][1] = (dp_b[i + 1][1] + dp_a[i][j]) % mod;
}
inc(j, 1, min(i - 1, k)) {
dp_a[i + 1][1] = (dp_a[i + 1][1] + dp_b[i][j]) % mod;
if (j + 1 <= k)
dp_b[i + 1][j + 1] =
(dp_b[i + 1][j + 1] + dp_b[i][j]) % mod;
}
}
memset(sum_a, 0, sizeof(sum_a));
memset(sum_b, 0, sizeof(sum_b));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= min(i, k); j++) {
sum_a[i] = (sum_a[i] + dp_a[i][j]) % mod;
sum_b[i] = (sum_b[i] + dp_b[i][j]) % mod;
}
}
ll res = 0;
for (int i = 1; i <= n; i++) {
int l = __gcd(i, n);
//循环节长度
for (int j = 2; j <= min(k, l - 1); j++) {
//首尾a之和
res = (res + (j - 1) * sum_a[l - j]) % mod;
}
//结尾b
res = (res + sum_b[l]) % mod;
if (k >= n) res++; //全a
}
printf("%lld\n", res * 2 * ksm((ll)n, mod - 2LL) % mod);
}
}

 

牛客挑战赛34 C 远山的占卜

题意: 给一个长度为 2n 的圆环染色, 一共有 k 种颜色, 经过旋转, 交换对角的点的颜色视为同构, T组数据. 问有多少种染色方案. T ≤ 2222,1 ≤ n, k < 19260817

思路: 这题除了旋转置换, 多出了一个交换对角的点的操作. 这里把对角的两个点视为"一体"的, 这个整体有 k × (k + 1) / 2 种染色方案. 选取连续的半个圆, 相当于对 n 个点进行 k × (k + 1) / 2 染色, 套用Pólya 定理即可.

view code
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inc(i, l, r) for (int i = l; i <= r; i++) const int mod = 19260817; int t;
ll n, k; const int maxnum = mod;
int prim[maxnum], pvis[maxnum + 5], pcnt, phi[maxnum + 5]; void getprim() {
phi[1] = 1;
for (int i = 2; i <= maxnum; i++) {
if (!pvis[i]) prim[++pcnt] = i, phi[i] = i - 1;
for (int j = 1; j <= pcnt && (ll)prim[j] * i <= maxnum; j++) {
pvis[prim[j] * i] = 1;
if (i % prim[j] == 0) {
phi[i * prim[j]] = phi[i] * prim[j];
break;
}
phi[i * prim[j]] = phi[i] * (prim[j] - 1);
}
}
} inline ll ksm(ll a, ll n) {
a %= mod;
ll r = 1;
while (n) {
if (n & 1) r = r * a % mod;
a = a * a % mod;
n >>= 1;
}
return r;
} int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
getprim();
cin >> t;
while (t--) {
cin >> n >> k;
k = k * (k + 1) / 2;
vector<int> divs;
for (int i = 1; i <= n / i; i++) {
if (n % i == 0) {
divs.push_back(i);
if (i < n / i) divs.push_back(n / i);
}
}
ll res = 0;
for (int d : divs) {
res = (res + phi[n / d] * ksm(k, (ll)d)) % mod;
}
cout << res * ksm(n, mod - 2LL) % mod << "\n";
}
}

疑惑: 这题我起初是认为交换对角的点也是一种置换, 但是这样子的话样例都解释不了. 未解, 难道说交换对角不属于置换?

 

Polya 定理相关题目的更多相关文章

  1. Burnside引理和Polya定理

    转载自:https://blog.csdn.net/whereisherofrom/article/details/79631703 Burnside引理 笔者第一次看到Burnside引理那个公式的 ...

  2. POJ 2409 Let it Bead:置换群 Polya定理

    题目链接:http://poj.org/problem?id=2409 题意: 有一串n个珠子穿起来的项链,你有k种颜色来给每一个珠子染色. 问你染色后有多少种不同的项链. 注:“不同”的概念是指无论 ...

  3. 【群论】polya定理

    对Polya定理的个人认识     我们先来看一道经典题目:     He's Circles(SGU 294)         有一个长度为N的环,上面写着“X”和“E”,问本质不同的环有多少个(不 ...

  4. POJ 2409 Let it Bead(Polya定理)

    点我看题目 题意 :给你c种颜色的n个珠子,问你可以组成多少种形式. 思路 :polya定理的应用,与1286差不多一样,代码一改就可以交....POJ 1286题解 #include <std ...

  5. POJ 1286 Necklace of Beads(Polya定理)

    点我看题目 题意 :给你3个颜色的n个珠子,能组成多少不同形式的项链. 思路 :这个题分类就是polya定理,这个定理看起来真的是很麻烦啊T_T.......看了有个人写的不错: Polya定理: ( ...

  6. 百练_2409 Let it Bead(Polya定理)

    描述 "Let it Bead" company is located upstairs at 700 Cannery Row in Monterey, CA. As you ca ...

  7. polya定理小结

    polya的精髓就在与对循环节的寻找,其中常遇到的问题就是项链染色类问题. 当项链旋转时有n种置换,循环节的个数分别是gcd(n, i); 当项链翻转时有n种置换,其中当项链珠子数位奇数时,循环节的个 ...

  8. HDU 4633 Who's Aunt Zhang (Polya定理+快速幂)

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4633 典型的Polya定理: 思路:根据Burnside引理,等价类个数等于所有的置换群中的不动点的个 ...

  9. [bzoj1488][HNOI2009]图的同构——Polya定理

    题目大意 求两两互不同构的含n个点的简单图有多少种. 简单图是关联一对顶点的无向边不多于一条的不含自环的图. a图与b图被认为是同构的是指a图的顶点经过一定的重新标号以后,a图的顶点集和边集能完全与b ...

随机推荐

  1. 设计模式-12组合模式(Composite Pattern)

    1.模式动机 很多时候会存在"部分-整体"的关系,例如:大学中的部门与学院.总公司中的部门与分公司.学习用品中的书与书包.在软件开发中也是这样,例如,文件系统中的文件与文件夹.窗体 ...

  2. 三个值得期待的JavaScript新功能!

    让我们来看看JavaScript中一些有用的即将推出的功能.您将看到他们的语法,链接以及时了解他们的进度,我们将编写一个小型测试套件,以展示如何立即开始使用这些提案! JavaScript是如何更新迭 ...

  3. 《52讲轻松搞定网络爬虫》读书笔记 —— HTTP基本原理

    URI 和 URL URI :Uniform Resource Identifier,即统一资源标志符, URL :Universal Resource Locator,即统一资源定位符. 举栗子,加 ...

  4. 使用Github Packages功能上传nuget包到Github

    前几天微软收购npm的新闻对于软粉来收很是振奋.微软收购npm很可能是为了加强Github Packages.目前Github,Typescript,VSCode,npm这些开源社区的重磅工具全部都在 ...

  5. vs 如何将dll打包到exe中

    方法如下:首先需要安装NuGet 然后安装Fody.Costura 重新启动vs 编译项目即可 虽然根目录下还生成了dll但是你的程序已经可以脱离dll运行了,其实是将你的dll打入了exe中你可以看 ...

  6. How to do error checking in CUDA(如何在CUDA里做错误检查)

    https://codeyarns.com/2011/03/02/how-to-do-error-checking-in-cuda/ Error checks in CUDA code can hel ...

  7. Deep Protein Methylation Profiling by Combined Chemical and Immunoaffinity Approaches Reveals Novel PRMT1 Targets (结合层析法和免疫沉淀法的蛋白甲基化的深度检测技术发现了PRMT1新的靶标蛋白)

    题目:Deep Protein Methylation Profiling by Combined Chemical and Immunoaffinity Approaches Reveals Nov ...

  8. java 获取 list 集合获取指定的 字段 数组

    /** * * AdminEntity 管理员实体类 * getAdminId 获取管理员实体类中的id * */ @Testvoid adminIdList () { List<AdminEn ...

  9. Python异常处理,将异常写入到一个文件

    '''定义一个函数func(urllist) urllist:为URL的列表,例如:['http://xx.com','http://www.xx.com','http://www.xxx.com'. ...

  10. 学习vue前的准备工作

    起步 1.扎实的HTML/CSS/Javascript基本功,这是前置条件. 2.不要用任何的构建项目工具,只用最简单的<script>,把教程里的例子模仿一遍,理解用法.不推荐上来就直接 ...