参考知识链接

 

关于枚举旋转置换:

  前两题都是枚举了 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. springboot自动装配原理回顾、配置文件分析

    配置文件 spring boot官方文档 官方外部配置文件说明参考文档 自动配置原理分析 1. SpringBoot启动的时候加载主配置类,开启了自动配置功能@EnableAutoConfigurat ...

  2. 菜鸟系列Golang学习 — 切片

    切片简介 切片也是一种数据类型,在Golang中,切片底层基于数组实现的. 我们定义切片如下 var slice []int 切片之所以出现,是为了更好的利用资源,管理数据,如果使用数组,则我们一开始 ...

  3. 从零开始打造 Mock 平台 - 核心篇

    前言 最近一直在捣鼓毕设,准备做的是一个基于前后端开发的Mock平台,前期花了很多时间完成了功能模块的交互.现在进度推到如何设计核心功能,也就是Mock数据的解析. 根据之前的需求设定加上一些思考,用 ...

  4. Vue方式自动打开浏览器配置

    Vue方式自动打开浏览器配置 1. 通过 package.json 配置项目 // 必须是符合规范的json语法 "vue": { "devServer": { ...

  5. socket TCP 从0实现音频传输 ALSA 播放

    RTP标准是采用 UDP 发送,有不少现成的开源库,但不在本文讨论的范围内.UDP 用户数据报,不提供流程,安全传输的功能,但速度快,能提供多播,广播,没有序列号 SEQ ,有 MTU 限制,1500 ...

  6. 数据结构 5 哈希表/HashMap 、自动扩容、多线程会出现的问题

    上一节,我们已经介绍了最重要的B树以及B+树,使用的情况以及区别的内容.当然,本节课,我们将学习重要的一个数据结构.哈希表 哈希表 哈希也常被称作是散列表,为什么要这么称呼呢,散列.散列.其元素分布较 ...

  7. 智慧树刷网课python脚本

    0x00 写在前面 疫情期间肯定有很多小伙伴需要上网课,但是有些网课我们感觉十分的鸡肋,自己不感兴趣,又必须要学 所以我写了这个刷网课的小程序,一方面是锻炼自己的爬虫技术,另一方面也给同学们节约宝贵的 ...

  8. javaScript 基础知识汇总 (十五)

    1.模块简介 什么是模块: 模块就是一个文件,一个脚本,通过关键字export 和 import 交换模块之间的功能. export 关键字表示在当前模块之外可以访问的变量和功能. import 关键 ...

  9. Java多线程详解(转载)

    林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 本文主要讲了java中多线程的使用方法.线程同步.线程数据传递.线程状态及相应的一些线程函数用 ...

  10. spring给容器中注入组件的几种方式

    目录 环境搭建 spring给容器中注入组件 1.包扫描+组件标注注解(@Controller/@Service/@Repository/@Component)适用于把自己写的类加入组件(默认ID类名 ...