Description

Antonio 最近对有机化学比较感兴趣,他想请你帮助他快速计算出某种烃类的同分异
构体的数目。 
为了表述方便,我们作出如下定义: 
  环烷烃: 具有n 个碳原子的环烷烃可以表示成一张具有n 个顶点n 条边的无向连通
简单图(基环+外向树)。每个顶点的度数不超过 4。 
  M-环烷烃:至多有m 个顶点在环上的环烷烃。(注意环上至少有 3 个顶点,因为
任意两个顶点之间至多只能有1 条边)。 
 同构:假设结构A和结构B 均具有n 个碳原子,A和B 同构当且仅当能够对A和
B 中的每个碳原子都按照 1~n 编号,使得对于编号为 v1 和 v2 的两个碳原子,他
们在 A中存在边相连当且仅当他们在 B中存在边相连。(换言之,A和 B对应的图
同构)。 
现在,给出n, m,Antonio 希望你帮助他统计有多少种互不同构的含有n 个碳原子的
m-环烷烃。由于这个数量可能很大,你只需要输出它对p 的余数。(p是一个素数)。 
在本题中,我们不考虑某结构在化学上是否能够稳定存在,也不考虑其他的异构方式。

Input

输入文件只有一行,用空格隔开的三个整数n, m, p 。保证有m <=n,p为素数。

Output

输出文件有且仅有一行,表示具有n 个碳原子的互不同构的m-环烷烃的数量,对 p的
余数。
先处理出根的度为2,其余点度<=4的无标号有根树的方案数
环有旋转和翻转两种变换,由于m>=3,构成的置换群阶为2m,用burnside引理处理
旋转k(0<=k<m)步可以形成gcd(m,k)个等价类,每个等价类包含m/gcd(m,k)个位置
旋转+翻转需要分奇偶处理:
 若m为奇数,则有m个这种置换,形成(m+1)/2个等价类,其中一个等价类包含1个位置,其余包含2个位置
 若m为偶数
  则有m/2个置换形成m/2个等价类,每个等价类包含2个位置
  另有m/2个置换形成m/2+1个等价类,其中两个等价类包含1个位置,其余包含2个位置
#include<cstdio>
typedef unsigned long long u64;
typedef unsigned int u32;
int n,m;
u32 P;
int gcd(int a,int b){
for(int c;b;c=a,a=b,b=c%b);
return a;
}
int phi(int n){
int v=n;
for(int i=;i*i<=n;++i)if(n%i==){
do n/=i;while(n%i==);
v=v/i*(i-);
}
if(n>)v=v/n*(n-);
return v;
}
inline u32 fix(int a){
return a+(a>>&P);
}
struct num{
u32 x;
num(u32 a=):x(a){}
num operator+(num w){return fix(x+w.x-P);}
num operator*(num w){return u64(x)*w.x%P;}
void operator+=(num w){x=fix(x+w.x-P);}
};
num s[][],gs[],iv[],f0[][],f1[][],ans;
void cal(int m,int n){
int g=gcd(n,m);
num v=;
for(int d=;d<=g;++d)if(g%d==)v+=f0[m/d][n/d]*phi(d);
v+=f1[m][n]*m;
ans+=v*iv[m*];
}
int main(){
scanf("%d%d%u",&n,&m,&P);
if(m>n)m=n;
s[][]=iv[]=;
for(int i=;i<=;++i)iv[i]=iv[P%i]*(P-P/i);
for(int i=;i<=n;++i){
f0[][i]=f1[][i]=s[][i-]+s[][i-]+s[][i-];
gs[]=f0[][i]+s[][i-];
for(int j=;j<=;++j)gs[j]=gs[j-]*(gs[]+(j-))*iv[j];
for(int j=;j;--j){
for(int k=n;k>=i;--k){
for(int t=;t<=j;++t){
int w=k-t*i;
if(w>=)s[j][k]+=gs[t]*s[j-t][w];
}
}
}
}
for(int i=;i<=m;++i){
for(int j=i;j<=n;++j){
for(int k=;k<j;++k)f0[i][j]+=f0[i-][j-k]*f0[][k];
if(i&){
for(int k=;k<j;k+=)f1[i][j]+=f0[i>>][k>>]*f0[][j-k];
}else{
for(int k=;k<j;++k)f1[i][j]+=f1[i-][j-k]*f0[][k];
if(~j&)f1[i][j]+=f0[i>>][j>>];
f1[i][j]=f1[i][j]*iv[];
}
}
}
for(int i=;i<=m;++i)cal(i,n);
printf("%d\n",ans.x);
return ;
}

bzoj 2601: [Jsoi2011]同分异构体计数的更多相关文章

  1. BZOJ 4517: [Sdoi2016]排列计数

    4517: [Sdoi2016]排列计数 Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 911  Solved: 566[Submit][Status ...

  2. [BZOJ]1016 JSOI2008 最小生成树计数

    最小生成树计数 题目描述 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小生成树就是不同 ...

  3. bzoj 2209: [Jsoi2011]括号序列 splay

    2209: [Jsoi2011]括号序列 Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 833  Solved: 392[Submit][Status ...

  4. [BZOJ 1016] [JSOI2008] 最小生成树计数 【DFS】

    题目链接:BZOJ - 1016 题目分析 最小生成树的两个性质: 同一个图的最小生成树,满足: 1)同一种权值的边的个数相等 2)用Kruscal按照从小到大,处理完某一种权值的所有边后,图的连通性 ...

  5. 数学(错排):BZOJ 4517: [Sdoi2016]排列计数

    4517: [Sdoi2016]排列计数 Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 693  Solved: 434[Submit][Status ...

  6. BZOJ 1016: [JSOI2008]最小生成树计数( kruskal + dfs )

    不同最小生成树中权值相同的边数量是一定的, 而且他们对连通性的贡献是一样的.对权值相同的边放在一起(至多10), 暴搜他们有多少种方案, 然后乘法原理. ----------------------- ...

  7. BZOJ 2209: [Jsoi2011]括号序列 [splay 括号]

    2209: [Jsoi2011]括号序列 Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 1111  Solved: 541[Submit][Statu ...

  8. BZOJ 4517: [Sdoi2016]排列计数 [容斥原理]

    4517: [Sdoi2016]排列计数 题意:多组询问,n的全排列中恰好m个不是错排的有多少个 容斥原理强行推♂倒她 $恰好m个不是错排 $ \[ =\ \ge m个不是错排 - \ge m+1个不 ...

  9. BZOJ 4710: [Jsoi2011]分特产 [容斥原理]

    4710: [Jsoi2011]分特产 题意:m种物品分给n个同学,每个同学至少有一个物品,求方案数 对于每种物品是独立的,就是分成n组可以为空,然后可以用乘法原理合起来 容斥容斥 \[ 每个同学至少 ...

随机推荐

  1. AnsiStartsStr 和 空字符串

    function AnsiStartsStr(const ASubText, AText: string): Boolean; begin Result := AnsiSameStr(ASubText ...

  2. Code Sign error: Provisioning profile XXXX can't be found

    [iphone]Code Sign error: Provisioning profile XXXX can't be found 如果你更新了profile,再编译iphone项目,发现下面的错误, ...

  3. Android 获取联系人和电话号码

    获取联系人和电话号码 private void queryContactPhoneNumber() { String[] cols = {ContactsContract.PhoneLookup.DI ...

  4. vue 设置代理后 后端获取不到登录的session处理方法

    代理设置的 名称 必须是 远程后端的 项目名称 session才生效.

  5. MyEclipse junit测试问题initializationError

    问题的情况如上. 问题的解决方法居然是:选中函数的整行,而不是只选中函数名,如下图选中运行junit测试. TestMySQL.testDriverMannager1Unrooted Testsini ...

  6. BZOJ3473: 字符串【后缀数组+思维】

    Description 给定n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串? Input 第一行两个整数n,k. 接下来n行每行一个字符串. Output 一 ...

  7. UTF-8编码占几个字节?

    占2个字节的:带有附加符号的拉丁文.希腊文.西里尔字母.亚美尼亚语.希伯来文.阿拉伯文.叙利亚文及它拿字母则需要二个字节编码 占3个字节的:基本等同于GBK,含21000多个汉字 占4个字节的:中日韩 ...

  8. Python类之魔术方法

    一.什么是魔术方法? 在Python的方法,我们经常会遇见__XXX__(),这样的方法,我们一般称为"魔术方法",赶紧搬个小板凳,我们一起来看看魔术方法有啥神奇的地方,这些方法又 ...

  9. from表单的分向提交

    一:需求: 思路:document.form.action,表单分向提交,javascript提交表单同一个表单可以根据用户的选择,提交给不同的后台处理程序.即,表单的分向提交.如,在编写论坛程序时, ...

  10. Properties类与配置文件

    //加载文件public static void testLoadProperties() throws Exception { Properties properties = new Propert ...