题目链接

弱化版(其实完全一样)

u1s1,洛谷上这题的第一个题解写得很不错,可以参考


直接边讲Polya定理边做这题

问题引入:n颗珠子组成的手串,每颗珠子有两种不同的颜色, 如果两个手串能够在旋转或翻转之后完全一样,就称它们是等价的,对手串的等价类计数。我们先把手串破环为链,两个长度为n的01序列等价当且仅当能够在循环移位或翻转后完全一样,求等价类数量。

注意两个序列"相等"指的是外表完全相同,"等价"指的是能够通过转化后外表完全相同。

Polya定理说这个问题的答案是:\(\frac 1{|G|}\sum_{g\in G}c(g,X)\)。其中X表示所有外表不同的序列的集合;G表示把所有变换看成置换之后的置换群(置换群的概念请自行搜索);\(c(g,X)\)表示X中满足"将置换g施加到序列x上之后x的外表仍然不变"的元素x的个数,专业点说是不动点的个数。对于任意置换与等价类计数的问题,都可以用这个式子求。

具体证明可以看这里

对于这道题也是一样,这题中X是所有点有编号、点有权值(1-k)、边有权值(1/0表示存在或不存在)的n个点的无向完全图的集合;G是置换群(由于这题中的变换是给节点重新编号,所以G是所有1-n的排列的集合);\(c(g,X)\)表示X中满足"将置换g施加到无向图x上之后x的外表仍然不变"的元素x的个数。

假设现在我们枚举g,考虑求出\(c(g,X)\)。对于g,如果我们把\(i\to g_i\)连有向边,是可以得到若干环的,假设这些环的大小从小到大排列为\(b_1,b_2\cdots b_m\)。对于其中的一条边\(u\to v\),原图中的节点u在经过变换之后它的编号就要变成v了。考虑如果想让变换前后的图外表完全一样,这个图需要满足什么条件。首先g连出的每一个环内的点权值都必须相同,且所有的环必须覆盖[1,k]中的全部颜色(题目要求,用dp预处理方案数即可)。接下来的限制其实跟上面那个弱化版一样,每个长度为\(b_i\)的环内的所有边被分成了\(\lfloor \frac {b_i}2 \rfloor\)类,每一类的权值都必须相等;两个长度为\(b_i,b_j\)的环之间的\(b_ib_j\)条边被分成了\(gcd(b_i,b_j)\)类,每一类的权值都必须相等。

对于一个序列\(b_1,b_2\cdots b_m\),我们已经能快速地用上面的方法算出它对答案的贡献,现在还要知道有多少个g对应这个序列,其实就是个简单的排列组合问题。令\(c_i\)表示b序列中值i出现的次数。对应这个b序列的g的个数为:\(\frac{n!}{\prod_{i=1}^m, b_i!}\cdot (\prod_{i=1}^m (b_i-1)!)\cdot \frac 1{\prod c_i! }\),其中第一部分为多重组合数,用来选出每个环的元素;第二部分是把每个环中的所有元素排成有序环的方案数;第三部分是除掉相同的\(b_i\)算重的次数。

列一下最后答案的式子:\(ans=\sum_{b_1\cdots b_m} \frac 1{\prod b_i\prod c_i!}\cdot dp_{m,k}\cdot 2^{(\sum \lfloor \frac {b_i}2 \rfloor )+\sum_{i,j}gcd(b_i,b_j)}\),其中\(dp_{i,j}\)表示1-i一共i个元素染色,且占了\([1,j]\)中的所有颜色的方案数。

我们直接暴搜枚举\(b\)数组所有可能的情况,然后用上面的方法暴力计算就行。时间复杂度\(O(能过)\)。

点击查看代码
#include <bits/stdc++.h>

#define rep(i,n) for(int i=0;i<n;++i)
#define repn(i,n) for(int i=1;i<=n;++i)
#define LL long long
#define pii pair <int,int>
#define pdd pair <double,double>
#define fi first
#define se second
#define mpr make_pair
#define pb push_back void fileio()
{
#ifdef LGS
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
}
void termin()
{
#ifdef LGS
std::cout<<"\n\nEXECUTION TERMINATED";
#endif
exit(0);
} using namespace std; LL n,k,MOD,ans=0,fac[40],inv[40],rinv[40],dp[40][40];
vector <LL> d; LL qpow(LL x,LL a)
{
LL res=x,ret=1;
while(a>0)
{
if(a&1) (ret*=res)%=MOD;
a>>=1;
(res*=res)%=MOD;
}
return ret;
} void dfs(LL sum,LL mx)
{
if(sum==n)
{
LL res=1;
rep(i,d.size()) (res*=rinv[d[i]])%=MOD;
map <LL,LL> mp;rep(i,d.size()) ++mp[d[i]];
for(auto it:mp) (res*=inv[it.se])%=MOD;
(res*=dp[d.size()][k])%=MOD;
LL tot=0;
rep(i,d.size()) tot+=d[i]/2;
rep(i,d.size()) for(int j=i+1;j<d.size();++j) tot+=__gcd(d[i],d[j]);
(res*=qpow(2,tot))%=MOD;
(ans+=res)%=MOD;
return;
}
for(LL nxt=max(mx,1LL);nxt<=n-sum;++nxt)
{
d.pb(nxt);
dfs(sum+nxt,nxt);
d.pop_back();
}
} int main()
{
fileio(); cin>>n>>k>>MOD;
dp[0][0]=1;
rep(i,n+3) rep(j,k+1) if(dp[i][j])
{
(dp[i+1][j]+=dp[i][j]*j)%=MOD;
(dp[i+1][j+1]+=dp[i][j]*(j+1))%=MOD;
}
fac[0]=1;repn(i,35) fac[i]=fac[i-1]*i%MOD;
rep(i,34) inv[i]=qpow(fac[i],MOD-2),rinv[i]=qpow(i,MOD-2);
dfs(0,0);
cout<<ans<<endl; termin();
}

Atcoder Beginner Contest ABC 284 Ex Count Unlabeled Graphs 题解 (Polya定理)的更多相关文章

  1. [题解] Atcoder Beginner Contest ABC 270 G Ex 题解

    点我看题 G - Sequence in mod P 稍微观察一下就会发现,进行x次操作后的结果是\(A^xS+(1+\cdots +A^{x-1})B\).如果没有右边那一坨关于B的东西,那我们要求 ...

  2. [题解] Atcoder Beginner Contest ABC 265 Ex No-capture Lance Game DP,二维FFT

    题目 首先明确先手的棋子是往左走的,将其称为棋子1:后手的棋子是往右走的,将其称为棋子2. 如果有一些行满足1在2右边,也就是面对面,那其实就是一个nim,每一行都是一堆石子,数量是两个棋子之间的空格 ...

  3. AtCoder Beginner Contest 053 ABCD题

    A - ABC/ARC Time limit : 2sec / Memory limit : 256MB Score : 100 points Problem Statement Smeke has ...

  4. AtCoder Beginner Contest 100 2018/06/16

    A - Happy Birthday! Time limit : 2sec / Memory limit : 1000MB Score: 100 points Problem Statement E8 ...

  5. AtCoder Beginner Contest 076

    A - Rating Goal Time limit : 2sec / Memory limit : 256MB Score : 100 points Problem Statement Takaha ...

  6. AtCoder Beginner Contest 068 ABCD题

    A - ABCxxx Time limit : 2sec / Memory limit : 256MB Score : 100 points Problem Statement This contes ...

  7. AtCoder Beginner Contest 161

    比赛链接:https://atcoder.jp/contests/abc161/tasks AtCoder Beginner Contest 161 第一次打AtCoder的比赛,因为是日本的网站终于 ...

  8. AtCoder Beginner Contest 224

    AtCoder Beginner Contest 224 A - Tires 思路分析: 判断最后一个字符即可. 代码如下: #include <bits/stdc++.h> using ...

  9. KYOCERA Programming Contest 2021(AtCoder Beginner Contest 200) 题解

    KYOCERA Programming Contest 2021(AtCoder Beginner Contest 200) 题解 哦淦我已经菜到被ABC吊打了. A - Century 首先把当前年 ...

  10. AtCoder Beginner Contest 184 题解

    AtCoder Beginner Contest 184 题解 目录 AtCoder Beginner Contest 184 题解 A - Determinant B - Quizzes C - S ...

随机推荐

  1. 记录一次使用git工具拉取coding上代码密码账号错误的经历

    1.忘记密码 1.另外的一个位置

  2. 学生管理系统(C语言简单实现)

    仅供借鉴.仅供借鉴.仅供借鉴(整理了一下大一C语言每个章节的练习题.没得题目.只有程序了) 文章目录 1 .实训名称 2.实训目的及要求 3. 源码 4.实验小结 1 .实训名称 实训12:文件 2. ...

  3. 题解UVA10948 The primary problem

    前言 前置 \(\sf{Solution}\) 既然有了 \(n\) ,那找出 \(a\) 和 \(b\) 就只要枚举 \(a\) 的范围 \(1\sim n\),判断 \(a\) 和 \(n-a\) ...

  4. PMM实现监控Mysql-MGR

    一.docker安装PMM服务端 1.安装yum配置单元 # 如果已安装,略过此步 yum install -y yum-utils #yum配置单元 2.配置docker阿里云yum源 #配置doc ...

  5. C#怎么在生成解决方案的过程中执行perl脚本(C#早期绑定)

    转载 怎么在生成解决方案的过程中执行perl脚本 早期绑定在编译期间识别并检查方法.属性.函数,并在应用程序执行之前执行其他优化.在这个绑定中,编译器已经知道它是什么类型的对象以及它拥有的方法或属性. ...

  6. scp工具上传下载

    1.从本地复制到远程 scp local_file remote_username@remote_ip:remote_folder 或者 scp local_file remote_username@ ...

  7. bugku 计算器

    打开就一个输入框和验证,尝试后发现输入框限制了位数,这还不简单,F12直接修改表单长度试试 成功得到flag

  8. SpringBoot+hutool工具-数据库数据导出Excel

    hutool文档地址:https://www.hutool.cn/docs/#/ 导入依赖 <dependency> <groupId>cn.hutool</groupI ...

  9. X活手环的表盘自定义修改

    文章用到的所有工具及软件成品 前言 前几天我在某宝买了一个智能手环,无奈软件中的表盘太少,所有我想着修改一下app中的资源文件. 反编译APK 这里反编译APK用apktool工具就可以. apkto ...

  10. python调用程序路径中包空格,及包含特殊字符问题

    解决办法 import os s = r'"C:\Program Files\Google\Chrome\Application\chrome.exe"' print(s) os. ...