题目链接

题意

求出 \(n\) 个珠子的在旋转同构意义下的手 个数,满足以下条件:

恰好有 \(m\) 个黑色珠子,其余为白色。

黑色珠子形成的最长连续段不能超过 \(k\) 个。

Sol

考虑 \(Burnside\) 引理\(/Polya\) 定理 , 那么答案就是:

\[\frac{\sum_{i=1}^n f(i)}{n}
\]

\(f(i)\) 表示在转 \(i\) 次的置换下所有合法染色方案中能够产生不动点的个数。这样我们就不用考虑旋转同构的问题了。

对于转 \(i\) 次的一个置换 , 显然它把这个长度为 n 的链分成了 \(gcd(n,i)\) 个环(也就是循环) , 那么一种方案要是不动点的话就必须满足这些环中的所有元素都是同色。

我们设 \(d=gcd(n,i)\) , 把式子再次变形:

\[ans=\frac{1}{n} \bigg( \sum_{d|n}^n F(d) \sum_{i=1}^{n}\boldsymbol[gcd(i,n)=d \boldsymbol]\bigg)
\]

这是个常见的式子了, \(n\) 中与 \(i\) 的 \(gcd\) 是 \(d\) 的数有 \(\varphi(\frac{n}{d})\) 个。

那么:

\[ans=\frac{1}{n} \bigg( \sum_{d|n}^n F(d) \varphi(\frac{n}{d}) \bigg)
\]

\(F(d)\)表示现在有 \(\frac{n}{d}\) 个循环 , 模\(d\)意义下在同一个剩余系中的珠子颜色要相同且黑色珠子不能有连续的超过 \(k\) 个 , 求合法的染色方案数。

因为当 \(d\) 确定下来的话 , 被分成的循环的情况也就确定了 , 模 \(d\) 相同的在一个环里。

既然这样 , 首先我们直接特判 \(n=m\) 的情况 , 这样由于染色的决策是一个循环的过程 , 每\(d\)个珠子之间就可以看作是互不影响了 , 于是就相当于我们现在有 \(d\) 个珠子 , 要给其中 \(\frac{m}{\frac{n}{d}}=\frac{md}{n}\) 个染成黑色 , 黑色段最长不能超过 \(k\) 个的合法方案数了。

由于是一个环直接做不好考虑首尾 , 所以直接枚举首尾总共已经有 \(i\) 个球被染色 , 那么我们就希望求出 \(Paint(n,m,k)\) 表示有 \(n\) 个球排成一列 , 首尾已经都是白色的 , 现在要给中间的球染成黑色,满足黑色段最长不超过 \(k\) 的方案数。

由于球是等价的 , 这样我们可以把原问题变成 现在有 \(n-m\) 个球 , 要在其中的 \(n-m-1\) 个空隙里插入 \(m\) 个球 , 要求每个空隙里不能插入超过 \(k\) 个球 , 求方案数。

这是一个简单的容斥问题了 , 我们枚举至少有多少个空隙插入了多余 \(k\) 个球 , 剩下的就隔板法求一个方案数就行了。这里复杂度只有 \(O(\frac{m}{k})\)

然后我们由于要枚举环首尾有多少个黑珠子 , 所以单次计算一个 \(F\) 的复杂度是 \(O(m)\) 的

但是注意这里的 \(m\) 不是原来的 \(m\) 它是 \(\frac{md}{n}\)

如果我们用 \(d'\) 来替换 \(\frac{n}{d}\) , 这样复杂度就是 \(O(\sum_{d'|n}\frac{m}{d'})\)

\(d'\) 还必须是 m的约数 , 所以显然我们的复杂度是 \(gcd(n,m)\) 的约数和 ,可以轻松通过。

#include<bits/stdc++.h>
#define Set(a,b) memset(a,b,sizeof(a))
using namespace std;
const int N=1e6+10;
const int mod=998244353;
template <typename T> inline void init(T&x){
x=0;char ch=getchar();bool t=0;
for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') t=1;
for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+(ch-48);
if(t) x=-x;return;
}
typedef long long ll;
template <typename T>inline void Inc(T&x,int y){x+=y;if(x>=mod) x-=mod;return;}
template <typename T>inline void Dec(T&x,int y){x-=y;if(x < 0) x+=mod;return;}
template <typename T>inline int fpow(int x,T k){int ret=1;for(;k;k>>=1,x=(ll)x*x%mod) if(k&1) ret=(ll)ret*x%mod;return ret;}
int Sum(int x,int y){x+=y;if(x>=mod) return x-mod;return x;}
int Dif(int x,int y){x-=y;if(x < 0 ) return x+mod;return x;}
int n,m,k;
int gcd(int a,int b){return b? gcd(b,a%b):a;}
int pri[N],vis[N],cnt=0,phi[N],fac[N],finv[N];
inline int C(int n,int m){return n<m? 0:((ll)fac[n]*finv[m]%mod*finv[n-m]%mod);}
inline void Sieve(){
phi[1]=1;vis[1]=1;fac[0]=finv[0]=fac[1]=finv[1]=1;
int n=1e6;
for(int i=2;i<=n;++i) {
if(!vis[i]) pri[++cnt]=i,phi[i]=i-1;
fac[i]=(ll)fac[i-1]*i%mod;
for(int j=1;j<=cnt;++j){
int nt=i*pri[j];if(nt>n) break;
vis[nt]=1;
if(i%pri[j]==0) {phi[nt]=phi[i]*pri[j];break;}
phi[nt]=phi[i]*phi[pri[j]];
}
}
finv[n]=fpow(fac[n],mod-2);
for(int i=n-1;i;--i) finv[i]=(ll)finv[i+1]*(i+1)%mod;
return;
}
inline int Solve(int n,int m,int k){
if(!m) return 1;
++k;int mx=m/k;int ans=0;
for(int i=0;i<=mx;++i) {
int ret=m-i*k;
int res=(ll)C(n,i)*C(n+ret-1,n-1)%mod;
if(i&1) Dec(ans,res);else Inc(ans,res);
}
return ans;
}
inline int Calc(int n,int m){
int ret=0;int ed=min(m,k);
for(int i=0;i<=ed;++i) Inc(ret,(ll)(i+1)*Solve(n-m-1,m-i,k)%mod);
return ret;
}
int main()
{
Sieve();init(n),init(m),init(k);
if(n==m) {puts((k>=n)? "1":"0");return 0;}
int ans=0;
for(int i=1;i*i<=n;++i) {
if(n%i==0) {
if((m*i%n)==0) Inc(ans,(ll)Calc(i,m*i/n)*phi[n/i]%mod);
if(n/i!=i&&m%i==0) Inc(ans,(ll)Calc(n/i,m/i)*phi[i]%mod);
}
}
ans=(ll)ans*fpow(n,mod-2)%mod;
printf("%d\n",ans);
return 0;
}

【LuoguP4916】魔力环的更多相关文章

  1. Luogu4916 魔力环 莫比乌斯反演、组合、生成函数

    传送门 先不考虑循环同构的限制,那么对于一个满足条件的序列,如果它的循环节长度为\(d\),那么与它同构的环在答案中就会贡献\(d\)次. 所以如果设\(f_i\)表示循环节长度恰好为\(i\)的满足 ...

  2. [Luogu4916]魔力环[Burnside引理、组合计数、容斥]

    题意 题目链接 分析 sπo yyb 代码 #include<bits/stdc++.h> using namespace std; typedef long long LL; #defi ...

  3. 【Luogu4916】魔力环(Burnside引理,组合计数)

    考虑\(Burside\)引理,设\(f(x)\)表示置换拆成循环的个数为\(x\)时的答案,那么最终的结果就是\(\displaystyle \frac{\sum_{i=1}^n f(gcd(i,n ...

  4. luogu P4916 魔力环

    传送门 表示这种\(Burnside\)定理之类的东西一用就忘qwq 题目要求不同染色方案数,因为变换方式只有旋转,所以只有\(n\)个置换,然后可能会出现某种方案有循环节,这个循环节长度显然要是\( ...

  5. LOJ6519. 魔力环(莫比乌斯反演+生成函数)

    题目链接 https://loj.ac/problem/6519 题解 这里给出的解法基于莫比乌斯反演.可以用群论计数的相关方法代替莫比乌斯反演,但两种方法的核心部分是一样的. 环计数的常见套路就是将 ...

  6. [jzoj 6084] [GDOI2019模拟2019.3.25] 礼物 [luogu 4916] 魔力环 解题报告(莫比乌斯反演+生成函数)

    题目链接: https://jzoj.net/senior/#main/show/6084 https://www.luogu.org/problemnew/show/P4916 题目: 题解: 注: ...

  7. loj6519 魔力环

    解题思路 考虑顺时针旋转 \(i\) 步得到的结果,根据Burnside引理,有 \[ Ans=\frac{\sum\limits_{i=0}^{n-1}C(i)}{n} \] \(C(i)\) 为旋 ...

  8. 「MtOI2018」魔力环

    首先发现是经典的循环置换本质不同个数模型,根据 Burnside 引理: \[|X / G| = \frac{1}{|G|}\sum\limits_{g \in G} |X ^ g| \] 考虑第 \ ...

  9. GOOD BYE OI

    大米饼正式退役了,OI给我带来很多东西 我会的数学知识基本都在下面了 博客园的评论区问题如果我看到了应该是会尽力回答的... 这也是我作为一个OIer最后一次讲课的讲稿 20190731 多项式乘法 ...

随机推荐

  1. freemarker程序开发

    1.程序开发入门 1.1 创建配置实例 首先,你应该创建一个freemarker.template.Configuration的实例,然后调整它的设置.Configuration实例是存储FreeMa ...

  2. promise不会被return触发, 一个promise对象中不会被Promise.reject触发

    1. let a = new Promise((resolve,reject)=>{ return 23 }) a; // promise <pending> 2. let a = ...

  3. Visdom可视化

    Visdom是基于Pytorch的可视化工具 安装方式: pip install visdom 因为Visdom本质上是一个Web服务器,把数据渲染到网页上,因此首先需要运行这个 服务器,如下: py ...

  4. java.lang.NoSuchMethodError: org.apache.spark.internal.Logging.$init$(Lorg/apache/spark/internal/Logging;)V

    1.sparkML的版本不对应 请参考官网找到对于版本, 比如我的 spark2.3.3          spark MLlib 也是2.3.3

  5. 深入理解java:2.3.2. 并发编程concurrent包 之重入锁/读写锁/条件锁

    重入锁 Java中的重入锁(即ReentrantLock)   与JVM内置锁(即synchronized)一样,是一种排它锁. ReentrantLock提供了多样化的同步,比如有时间限制的同步(定 ...

  6. ansible-playbook -l 选项

    -l <SUBSET>, --limit <SUBSET> further limit selected hosts to an additional pattern 限制脚本 ...

  7. 自定义SpringBoot启动控制台图标

    使用过SpringBoot的小伙伴众所周知,在启动的过程中,在控制台会首先打印spring的图标以及版本号(这里以IDEA为例) 如果需要更改这个打印图标的话, 需要以下步骤: 1.打开SpringB ...

  8. ESXi导出的CentOS7 ovf文件导入到workstation 无法打开GUI登录界面的问题解决方案

    1. 前几天将centos的机器导出为ovf 文件 然后使用 workstation 引入之后发现总是黑屏 然后有一个 横杠在闪 2. 解决办法是 修改centos的虚拟机配置文件,将显示器修改为这样 ...

  9. GUI程序原理分析

    1,Qt 是一套跨平台的程序设计库,这套程序设计库主要用于 GUI 方面的程序设计开发,所以本系列博文主要是利用C++介绍 GUI 程序设计技术: 2,命令行应用程序: 1,命令行应用程序的特点(Co ...

  10. linux 隐藏显示终端光标

    转载:http://blog.chinaunix.net/uid-20682890-id-3180911.html 一.使用shell 的 echo 命令实现. echo -ne <ctrl+v ...