分析

Attention!这道题的模数是\(1e8+7\)。

注意到循环同构会被认为是同一种方案,我们可以把顺时针旋转每个人的位置作为置换,容易发现这些置换一定会形成一个置换群,于是题目所求的所有合法的方案数便是这个置换群下等价类的数目,可以使用Burnside引理解决。

考虑如何求在置换“顺时针旋转\(x\)位置”下不动点的数目,可以发现这样的不动点的男女排列一定具有周期性,且\(gcd(n,x)\)是它的一个周期,这里可以自行画图理解一下。这样我们又再次简化了题目,我们现在只需考虑这一个周期了。

令\(d=gcd(n,x)\),首先进行如下的分类讨论:

  1. \(n \leq k\),这样不存在不合法的方案,返回\(2^d\)。

  2. \(n>k\)且\(d \leq k\),这样只要这个周期内不全是女生即是合法方案,返回\(2^d-1\)。

  3. \(n>k\)且\(d>k\),DP解决。

怎么DP?

\(f[i][j]\)表示不考虑循环的情况下,考虑到前\(i\)个人,最后\(j\)个人是女生的方案数。

\(g[i][j]\)表示不考虑循环的情况下,考虑到前\(i\)个人,保证第一个人是男生,最后\(j\)个人是女生的方案数。

显然有转移:

\[f[i][0]=\sum_{x=0}^{min(i-1,k)}f[i-1][x]
\]

\[f[i][j]=f[i-1][j-1]\ (j \neq 0)
\]

\(g[i][j]\)的转移与\(f[i][j]\)类似。

于是对于长度为\(i\)的区间,其合法方案数为\(\sum_{j=1}^{min(i,k)}f[i][j]-\sum_{j=k+1}^{min(i-1,2k)}g[i-j][0] \times (2k-j+1)\),这个可以直接预处理出来。

总结一下上面所提到的,在置换“顺时针旋转\(x\)位置”下的不动点,男女排列一定具有周期性,\(d=gcd(n,x)\)是其一个周期,我们只需要对这个区间进行讨论和计算,并统计到所有置换的不动点个数和中即可。

考虑到这样一个事实,\(\sum_{i=1}^{n}[gcd(i,n)=d]=\varphi(\frac{n}{d})\),所以可以直接枚举\(n\)的约数\(d\),然后计算\(d\)对答案的贡献。(这一步可有可无)

最后根据Burnside引理乘上一个\(n^{-1}\)。

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
#define rin(i,a,b) for(int i=(a);i<=(b);i++)
#define rec(i,a,b) for(int i=(a);i>=(b);i--)
#define trav(i,x) for(int i=head[(x)];i;i=e[i].nxt)
using std::cin;
using std::cout;
using std::endl;
typedef long long LL; inline int read(){
int x=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x;
} const int MAXN=2005;
const int MOD=1e8+7;
int n,k;
LL f[MAXN][MAXN],g[MAXN][MAXN],cnt[MAXN];
int prm[MAXN],phi[MAXN],pcnt;
bool vis[MAXN]; inline LL qpow(LL x,LL y){
LL ret=1,tt=x%MOD;
while(y){
if(y&1) ret=ret*tt%MOD;
tt=tt*tt%MOD;
y>>=1;
}
return ret;
} inline void pre_process1(){
phi[1]=1;
rin(i,2,n){
if(!vis[i]){
prm[++pcnt]=i;
phi[i]=i-1;
}
for(int j=1;j<=pcnt&&i*prm[j]<=n;j++){
vis[i*prm[j]]=1;
if(i%prm[j]==0){
phi[i*prm[j]]=phi[i]*prm[j];
break;
}
phi[i*prm[j]]=phi[i]*(prm[j]-1);
}
}
} inline void pre_process2(){
f[0][0]=f[1][0]=f[1][1]=g[1][0]=1;
rin(i,2,n){
f[i][0]=g[i][0]=0;
rin(j,0,std::min(i-1,k)){
f[i][0]+=f[i-1][j];
if(f[i][0]>=MOD) f[i][0]-=MOD;
}
rin(j,1,std::min(i,k)) f[i][j]=f[i-1][j-1];
rin(j,0,std::min(i-2,k)){
g[i][0]+=g[i-1][j];
if(g[i][0]>=MOD) g[i][0]-=MOD;
}
rin(j,1,std::min(i-1,k)) g[i][j]=g[i-1][j-1];
}
rin(i,1,n){
cnt[i]=0;
rin(j,0,std::min(i,k)){
cnt[i]+=f[i][j];
if(cnt[i]>=MOD) cnt[i]-=MOD;
}
rin(j,k+1,std::min(i-1,k<<1)){
cnt[i]-=g[i-j][0]*((k<<1)-j+1)%MOD;
if(cnt[i]<0) cnt[i]+=MOD;
}
}
} inline LL solve(int x){
if(x<=k){
if(k<n) return (qpow(2,x)-1+MOD)%MOD;
else return qpow(2,x);
}
else return cnt[x];
} int main(){
int T=read();
n=2000;
pre_process1();
while(T--){
n=read(),k=read();
pre_process2();
int lim=sqrt(n);
LL ans=0;
rin(i,1,lim){
if(n%i) continue;
ans=(ans+solve(i)*phi[n/i])%MOD;
if(i*i==n) continue;
ans=(ans+solve(n/i)*phi[i])%MOD;
}
printf("%lld\n",ans*qpow(n,MOD-2)%MOD);
}
return 0;
}

[BZOJ1547]周末晚会:Burnside引理+DP的更多相关文章

  1. BZOJ 1004 Cards(Burnside引理+DP)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1004 题意:三种颜色的扑克牌各有Sr,Sb,Sg张.给出m种置换.两种染色方案在某种置换 ...

  2. [BZOJ 1004] [HNOI2008] Cards 【Burnside引理 + DP】

    题目链接:BZOJ - 1004 题目分析 首先,几个定义和定理引理: 群:G是一个集合,*是定义在这个集合上的一个运算. 如果满足以下性质,那么(G, *)是一个群. 1)封闭性,对于任意 a, b ...

  3. BZOJ 1004 Cards(Burnside引理+DP)

    因为有着色数的限制,故使用Burnside引理. 添加一个元置换(1,2,,,n)形成m+1种置换,对于每个置换求出循环节的个数, 每个循环节的长度. 则ans=sigma(f(i))/(m+1) % ...

  4. bzoj1004: [HNOI2008]Cards(burnside引理+DP)

    题目大意:3种颜色,每种染si个,有m个置换,求所有本质不同的染色方案数. 置换群的burnside引理,还有个Pólya过几天再看看... burnside引理:有m个置换k种颜色,所有本质不同的染 ...

  5. bzoj 1004 burnside 引理+DP

    对于burnside引理需要枚举染色,这道题属于burnside的一种简单求解的方法,就是polya,我们可以使每一种置换中的循环节中的元素的颜色都相同,那么这样的话就可以直接DP了,我们可以将m个置 ...

  6. UVA11540 Sultan's Chandelier Burnside 引理 + DP

    题目传送门 https://vjudge.net/problem/UVA-11540 https://uva.onlinejudge.org/index.php?option=com_onlineju ...

  7. [bzoj 1004][HNOI 2008]Cards(Burnside引理+DP)

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1004 分析: 1.确定方向:肯定是组合数学问题,不是Polya就是Burnside,然后题目上 ...

  8. bzoj1547 周末晚会

    我们要求方案数,还是旋转同构的,想burnside,如果我们能计算出转i位不变的满足条件的数量,那么这道题我们就解决了. 考虑转i位时,设tmp=gcd(i,n),那么就共有tmp个循环节. 当tmp ...

  9. BZOJ 1004: [HNOI2008]Cards( 置换群 + burnside引理 + 背包dp + 乘法逆元 )

    题意保证了是一个置换群. 根据burnside引理, 答案为Σc(f) / (M+1). c(f)表示置换f的不动点数, 而题目限制了颜色的数量, 所以还得满足题目, 用背包dp来计算.dp(x,i, ...

随机推荐

  1. Java内存管理和回收

    转载自http://blog.csdn.net/cutesource/article/details/5906705 JVM内存组成结构 JVM栈由堆.栈.本地方法栈.方法区等部分组成,结构图如下所示 ...

  2. Java程序的运行过程,以及Java为什么能够跨平台

    Java程序运行机制  Java的运行主要分两步:先编译再解释执行 (1)先通过“编译器”将Java源程序(.java)编译成Java字节码文件(.class) (2)通过不同的虚拟机(JVM)将字节 ...

  3. APIView的流程分析

     APIView的流程分析 1.入口,因为视图类的继承APIView()的 as_view()是一个绑定类的方法 2.进入as_view(),正好这个as_view()有个返回值 返回的是dispat ...

  4. MySql 性能优化之 Explain

    MySQL 之 Explain 输出分析 背景 前面的文章写过 MySQL 的事务和锁,这篇文章我们来聊聊 MySQL 的 Explain,估计大家在工作或者面试中多多少少都会接触过这个.可能工作中实 ...

  5. QButtonGroup

    单选按钮和多选按钮,存放进QButtonGroup中 QButtonGroup方法来实现分组:将相同功能的按键,设为一个分组,然后可以进行 单选 或 多选 或 互斥单选 QAbstractButton ...

  6. faker数据填充详解

    安装 在laravel中已经自动集成,无需手动安装.如需在其他地方使用,可使用以下命令进行安装. composer require fzaninotto/faker 为Faker指定中文支持 可通过在 ...

  7. CSP-S全国模拟赛第二场 【nan】

    A.count 本场比赛最难的题... 隔板法组合数容斥 xjb 搞搞就好了 //by Judge #include<cstdio> #include<iostream> #d ...

  8. 发布一本用 GitBook 编辑的书

    在上一篇的文章里,我们已经写好了一本名叫 erdong-first-book 的书,但是在本地浏览很不方便,我们希望放到网络上,可以随时.方便的访问这个书籍.这个需求可以使用多种方式来实现,比如第一种 ...

  9. IIC通信协议详解

    IIC通信详解 IIC概述 IIC:两线式串行总线,它是由数据线SDA和时钟线SCL构成的串行总线,可发送和接收数据. 在CPU与被控IC之间.IC与IC之间进行双向传送,高速IIC总线一般可达400 ...

  10. MySQl查询语句大全

    综合使用 查询 目录: #----综合使用 书写顺序 select distinct * from '表名' where '限制条件' group by '分组依据' having '过滤条件' or ...