置换数量是阶乘级别的,但容易发现本质不同的点的置换数量仅仅是n的整数拆分个数,OEIS(或者写个dp或者暴力)一下会发现不是很大,当n=53时约在3e5左右。

  于是暴力枚举点的置换,并且发现根据点的置换我们得到的实际上是边的置换,暴力数一下循环节就好了。3e5*50*50,luogu上过掉了。诶怎么bzoj上开的时限总共只有4s啊?

  考虑数边置换的循环节时不那么暴力。显然两端点在同一循环内的边和在不同循环内的边是不可能处于同一边的循环的,并且第一种情况只与该循环长度有关,第二种情况只与两循环长度有关,先预处理一下就可以了,当然事实上也能直接推出来。不过这复杂度上并没有优化。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 60
char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<''||c>'')) c=getchar();return c;}
int gcd(int n,int m){return m==?n:gcd(m,n%m);}
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
int n,c,P,a[N],b[N],fac[N],inv[N],id[N][N],nxt[N*N],f[N],g[N][N],ans,T;
bool flag[N*N];
int ksm(int a,int k)
{
int s=;
for (;k;k>>=,a=1ll*a*a%P) if (k&) s=1ll*s*a%P;
return s;
}
int C(int n,int m){return 1ll*fac[n]*inv[m]%P*inv[n-m]%P;}
int calc(int m)
{
int s=,tot=n;
for (int i=;i<=m;i++)
{
int t=i;
while (t<m&&a[t+]==a[i]) t++;
s=1ll*s*inv[t-i+]%P;
for (int j=i;j<=t;j++)
s=1ll*s*C(tot,a[j])%P*fac[a[j]-]%P,tot-=a[j];
i=t;
}
tot=;
for (int i=;i<=m;i++) tot=(tot+f[a[i]])%P;
for (int i=;i<=m;i++)
for (int j=i+;j<=m;j++)
tot=(tot+g[a[i]][a[j]])%P;
return 1ll*s*ksm(c,tot)%P;
}
void dfs(int k,int n,int last)
{
if (n==) ans=(ans+calc(k-))%P;
if (n<last) return;
for (int i=last;i<=n;i++)
a[k]=i,dfs(k+,n-i,i);
}
int cycle()
{
int tot=;memset(flag,,T+);
for (int i=;i<=T;i++)
if (!flag[i])
{
int x=nxt[i];flag[i]=;tot++;
while (x!=i) flag[x]=,x=nxt[x];
}
return tot;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj1815.in","r",stdin);
freopen("bzoj1815.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
n=read(),c=read(),P=read();
fac[]=;for (int i=;i<=n;i++) fac[i]=1ll*fac[i-]*i%P;
inv[]=inv[]=;for (int i=;i<=n;i++) inv[i]=P-1ll*(P/i)*inv[P%i]%P;
for (int i=;i<=n;i++) inv[i]=1ll*inv[i-]*inv[i]%P;
for (int i=;i<=n;i++)
{
T=;
for (int x=;x<=i;x++)
for (int y=x+;y<=i;y++)
id[x][y]=id[y][x]=++T;
for (int x=;x<=i;x++)
for (int y=x+;y<=i;y++)
nxt[id[x][y]]=id[x%i+][y%i+];
f[i]=cycle();
}
for (int i=;i<=n;i++)
for (int j=i;j<=n;j++)
{
T=;
for (int x=;x<=i;x++)
for (int y=;y<=j;y++)
id[x][y]=++T;
for (int x=;x<=i;x++)
for (int y=;y<=j;y++)
nxt[id[x][y]]=id[x%i+][y%j+];
g[i][j]=g[j][i]=cycle();
}
dfs(,n,);
cout<<1ll*ans*inv[n]%P;
return ;
}

BZOJ1815 SHOI2006有色图(Polya定理)的更多相关文章

  1. BZOJ 1815: [Shoi2006]color 有色图(Polya定理)

    题意 如果一张无向完全图(完全图就是任意两个不同的顶点之间有且仅有一条边相连)的每条边都被染成了一种颜色,我们就称这种图为有色图. 如果两张有色图有相同数量的顶点,而且经过某种顶点编号的重排,能够使得 ...

  2. [BZOJ1815&BZOJ1488]有色图/图的同构(Polya定理)

    由于有很多本质相同的重复置换,我们先枚举各种长度的点循环分别有多少个,这个暴搜的复杂度不大,n=53时也只有3e5左右.对于每种搜索方案可以轻易求出它所代表的置换具体有多少个. 但我们搜索的是点置换组 ...

  3. BZOJ1815: [Shoi2006]color 有色图

    BZOJ1815: [Shoi2006]color 有色图 Description Input 输入三个整数N,M,P 1< = N <= 53 1< = M < = 1000 ...

  4. 洛谷 P4128 [SHOI2006]有色图 解题报告

    P4128 [SHOI2006]有色图 题目描述 如果一张无向完全图(完全图就是任意两个不同的顶点之间有且仅有一条边相连)的每条边都被染成了一种颜色,我们就称这种图为有色图.如果两张有色图有相同数量的 ...

  5. 【转】Polya定理

    转自:http://endlesscount.blog.163.com/blog/static/82119787201221324524202/ Polya定理 首先记Sn为有前n个正整数组成的集合, ...

  6. 【群论】polya定理

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

  7. [wikioi2926][AHOI2002]黑白瓷砖(Polya定理)

    小可可在课余的时候受美术老师的委派从事一项漆绘瓷砖的任务.首先把n(n+1)/2块正六边形瓷砖拼成三角形的形状,右图给出了n=3时拼成的“瓷砖三角形”.然后把每一块瓷砖漆成纯白色或者纯黑色,而且每块瓷 ...

  8. HDU 3923 Invoker(polya定理+逆元)

    Invoker Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 122768/62768 K (Java/Others)Total Su ...

  9. Polya定理

    http://www.cnblogs.com/wenruo/p/5304698.html 先看 Polya定理,Burnside引理回忆一下基础知识.总结的很棒. 一个置换就是集合到自身的一个双射,置 ...

随机推荐

  1. 委托、事件、匿名方法、Lambda

    一.委托(delegate)     定义:public delegate  void/类型  DefinedDelegate(参数1,参数2...) 委托是类型安全的. 委托实例:DefinedDe ...

  2. 有关java(初学笔记)

    JAVA的主要优势:跨平台性,可以在Linux,windows,mac三个系统上运行. 跨平台的核心:JAVA虚拟机--JVM 原理就是将Java语言在这个系统上翻译.JAVA在jvm上运行,jvm进 ...

  3. 大数据入门第十六天——流式计算之storm详解(一)入门与集群安装

    一.概述 今天起就正式进入了流式计算.这里先解释一下流式计算的概念 离线计算 离线计算:批量获取数据.批量传输数据.周期性批量计算数据.数据展示 代表技术:Sqoop批量导入数据.HDFS批量存储数据 ...

  4. JavaEE笔记(十二)

    代理的三种配置 beans配置文件 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=& ...

  5. Linux每天一个命令:iperf

    iperf命令 Iperf 是一个网络性能测试工具.Iperf可以测试最大TCP和UDP带宽性能,具有多种参数和UDP特性,可以根据需要调整,可以报告带宽.延迟抖动和数据包丢失.下载地址:https: ...

  6. PowerBI开发 第一篇:设计PowerBI报表

    PowerBI是微软新一代的交互式报表工具,把相关的静态数据转换为酷炫的可视化的,能够根据filter条件,对数据执行动态筛选,从不同的角度和粒度上分析数据.PowerBI主要由两部分组成:Power ...

  7. mysql基础(二)—— 简单sql

    查询 select * from company select c.code from company c; select m.bookname from myview m; (myview为视图) ...

  8. (2)学习笔记 ) ASP.NET CORE微服务 Micro-Service ---- .NetCore启动配置 和 .NetCoreWebApi

    什么是.Net Core?.Net Core是微软开发的另外一个可以跨Linux.Windows.mac等平台的.Net.Net Core相关知识看文章地步dotnet dllname.dll 运行P ...

  9. python 微信撤回消息

    import itchatfrom itchat.content import *import osimport reimport time# 文件临时存储页rec_tmp_dir = os.path ...

  10. zabbix监控docker容器状态

    前言:前段时间在部署zabbix,有个需求就是需要监控容器的状态 也就是cpu 内存 io的占用,于是就自己写了一个脚本,以及模板,在这里分享一下 嘿嘿 : ) 废话我也就不多说,直接开始 首选,za ...