Polya 定理相关题目
关于枚举旋转置换:
前两题都是枚举了 n 种旋转, 但这个可以优化到\(O(\sqrt{n})\) (这个其实是基本操作). 考虑到每个循环节的长度都是 n 的因数, 所以可以枚举 n 的因数, 再乘以这个因数的贡献, 即被计算了几次, 对于一个数 a, 如果gcd(a, n) == d, 那么 a 就对 d 产生了 1 次贡献, 而一共有\(\varphi{(n/d)}\)个这样的数.
题意: 有一串 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);
}
}
题意: 有两国的大使共 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);
}
}
题意: 给一个长度为 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 定理相关题目的更多相关文章
- Burnside引理和Polya定理
转载自:https://blog.csdn.net/whereisherofrom/article/details/79631703 Burnside引理 笔者第一次看到Burnside引理那个公式的 ...
- POJ 2409 Let it Bead:置换群 Polya定理
题目链接:http://poj.org/problem?id=2409 题意: 有一串n个珠子穿起来的项链,你有k种颜色来给每一个珠子染色. 问你染色后有多少种不同的项链. 注:“不同”的概念是指无论 ...
- 【群论】polya定理
对Polya定理的个人认识 我们先来看一道经典题目: He's Circles(SGU 294) 有一个长度为N的环,上面写着“X”和“E”,问本质不同的环有多少个(不 ...
- POJ 2409 Let it Bead(Polya定理)
点我看题目 题意 :给你c种颜色的n个珠子,问你可以组成多少种形式. 思路 :polya定理的应用,与1286差不多一样,代码一改就可以交....POJ 1286题解 #include <std ...
- POJ 1286 Necklace of Beads(Polya定理)
点我看题目 题意 :给你3个颜色的n个珠子,能组成多少不同形式的项链. 思路 :这个题分类就是polya定理,这个定理看起来真的是很麻烦啊T_T.......看了有个人写的不错: Polya定理: ( ...
- 百练_2409 Let it Bead(Polya定理)
描述 "Let it Bead" company is located upstairs at 700 Cannery Row in Monterey, CA. As you ca ...
- polya定理小结
polya的精髓就在与对循环节的寻找,其中常遇到的问题就是项链染色类问题. 当项链旋转时有n种置换,循环节的个数分别是gcd(n, i); 当项链翻转时有n种置换,其中当项链珠子数位奇数时,循环节的个 ...
- HDU 4633 Who's Aunt Zhang (Polya定理+快速幂)
题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4633 典型的Polya定理: 思路:根据Burnside引理,等价类个数等于所有的置换群中的不动点的个 ...
- [bzoj1488][HNOI2009]图的同构——Polya定理
题目大意 求两两互不同构的含n个点的简单图有多少种. 简单图是关联一对顶点的无向边不多于一条的不含自环的图. a图与b图被认为是同构的是指a图的顶点经过一定的重新标号以后,a图的顶点集和边集能完全与b ...
随机推荐
- Ado.net 02
1.连接字符串不同,连接池也不同 SqlConnection对象只能被打开一次.但是在Close()后再进行Open()操作.但是在Dispose()之后就不能再Open()了. 2.SqlDataA ...
- 组件(4):使用slot进行内容分发
组件的作用域(一) 父组件模板的内容在父组件作用域内编译:子组件模板的内容在子组件作用域内编译. 父子组件的编译相互独立,编译时只能使用各自作用域中的属性和方法,例如,你不可以在父组件模板内,将一个指 ...
- Go module学习笔记
一 go module 常用命令 模块维护:go mod command arguments创建模块:go mod init example.com/hello清除无用依赖: go mod tidy ...
- spring boot actuator服务监控与管理
1.引入actuator所需要的jar包 <dependency> <groupId>org.springframework.boot</groupId> < ...
- Matplotlib数据可视化(5):柱状图与直方图
柱状图和直方图是两种非常类似的统计图,区别在于: 直方图展示数据的分布,柱状图比较数据的大小. 直方图X轴为定量数据,柱状图X轴为分类数据.因此,直方图上的每个条形都是不可移动的,X轴上的区间是连 ...
- Await/Async
Async其实就是Generator函数的语法糖. 啥是语法糖?就是一种更容易让人理解,代码可读性更高的另外一种语法. const asyncRead = async function(){ cons ...
- AJAX轮询的实时监控画面
上一篇我们通过异步刷新Ajax 技术,来实现监控页面监控位号值的刷新,采用Ajax (Asynchronous Javascript And XML)技术,是指一种创建交互式.快速动态网页应用的网页开 ...
- pytest、tox、Jenkins实现python接口自动化持续集成
pytest介绍 pytest是一款强大的python测试工具,可以胜任各种级别的软件测试工作,可以自动查找测试用并执行,并且有丰富的基础库,可以大幅度提高用户编写测试用例的效率,具备可扩展性,用户自 ...
- CentOS安装docker ce的三种方式
参考文章: CentOS安装docker ce的三种方式: 1.环境 CentOS Linux release 7.6.1810 (Core) 2.卸载旧版本 sudo yum remove dock ...
- [译]ABP框架v2.3.0已经发布!
在新冠病毒的日子里,我们发布了ABP框架v2.3, 这篇文章将说明本次发布新增内容和过去的两周我们做了什么. 关于新冠病毒和我们的团队 关于冠状病毒的状况我们很难过.在Volosoft的团队,我们有不 ...