【LuoguP4916】魔力环
题意
求出 \(n\) 个珠子的在旋转同构意义下的手 环 个数,满足以下条件:
恰好有 \(m\) 个黑色珠子,其余为白色。
黑色珠子形成的最长连续段不能超过 \(k\) 个。
Sol
考虑 \(Burnside\) 引理\(/Polya\) 定理 , 那么答案就是:
\]
\(f(i)\) 表示在转 \(i\) 次的置换下所有合法染色方案中能够产生不动点的个数。这样我们就不用考虑旋转同构的问题了。
对于转 \(i\) 次的一个置换 , 显然它把这个长度为 n 的链分成了 \(gcd(n,i)\) 个环(也就是循环) , 那么一种方案要是不动点的话就必须满足这些环中的所有元素都是同色。
我们设 \(d=gcd(n,i)\) , 把式子再次变形:
\]
这是个常见的式子了, \(n\) 中与 \(i\) 的 \(gcd\) 是 \(d\) 的数有 \(\varphi(\frac{n}{d})\) 个。
那么:
\]
\(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】魔力环的更多相关文章
- Luogu4916 魔力环 莫比乌斯反演、组合、生成函数
传送门 先不考虑循环同构的限制,那么对于一个满足条件的序列,如果它的循环节长度为\(d\),那么与它同构的环在答案中就会贡献\(d\)次. 所以如果设\(f_i\)表示循环节长度恰好为\(i\)的满足 ...
- [Luogu4916]魔力环[Burnside引理、组合计数、容斥]
题意 题目链接 分析 sπo yyb 代码 #include<bits/stdc++.h> using namespace std; typedef long long LL; #defi ...
- 【Luogu4916】魔力环(Burnside引理,组合计数)
考虑\(Burside\)引理,设\(f(x)\)表示置换拆成循环的个数为\(x\)时的答案,那么最终的结果就是\(\displaystyle \frac{\sum_{i=1}^n f(gcd(i,n ...
- luogu P4916 魔力环
传送门 表示这种\(Burnside\)定理之类的东西一用就忘qwq 题目要求不同染色方案数,因为变换方式只有旋转,所以只有\(n\)个置换,然后可能会出现某种方案有循环节,这个循环节长度显然要是\( ...
- LOJ6519. 魔力环(莫比乌斯反演+生成函数)
题目链接 https://loj.ac/problem/6519 题解 这里给出的解法基于莫比乌斯反演.可以用群论计数的相关方法代替莫比乌斯反演,但两种方法的核心部分是一样的. 环计数的常见套路就是将 ...
- [jzoj 6084] [GDOI2019模拟2019.3.25] 礼物 [luogu 4916] 魔力环 解题报告(莫比乌斯反演+生成函数)
题目链接: https://jzoj.net/senior/#main/show/6084 https://www.luogu.org/problemnew/show/P4916 题目: 题解: 注: ...
- loj6519 魔力环
解题思路 考虑顺时针旋转 \(i\) 步得到的结果,根据Burnside引理,有 \[ Ans=\frac{\sum\limits_{i=0}^{n-1}C(i)}{n} \] \(C(i)\) 为旋 ...
- 「MtOI2018」魔力环
首先发现是经典的循环置换本质不同个数模型,根据 Burnside 引理: \[|X / G| = \frac{1}{|G|}\sum\limits_{g \in G} |X ^ g| \] 考虑第 \ ...
- GOOD BYE OI
大米饼正式退役了,OI给我带来很多东西 我会的数学知识基本都在下面了 博客园的评论区问题如果我看到了应该是会尽力回答的... 这也是我作为一个OIer最后一次讲课的讲稿 20190731 多项式乘法 ...
随机推荐
- java中? extends T 和? super T解析
转:https://blog.csdn.net/qq_25337221/article/details/81669630 PECS原则 最后看一下什么是PECS(Producer Extends Co ...
- RequestContextHolder
JShop简介:jshop是一套使用Java语言开发的B2C网店系统,致力于为个人和中小企业提供免费.好用的网店系统. 项目主页:http://git.oschina.net/dinguangx/js ...
- HTML CSS JS 特殊字符(转义)表
HTML有许多特殊的字符,您对此有多少了解?平时在WEB制作中,您又有用到多少?或者说你在平时使用之时,是否也会碰到,有许多特殊字符要如何打印出来?比如说“笑脸”,比如说“版权号”.要是你用时忘记了这 ...
- JavaScript对象之--- RegExp
1.概述 正则表达式是描述字符模式的对象. 正则表达式用于对字符串模式匹配以及检索替换: 2.语法 前者为模式,后者为修饰符. var reg = new RegExp( "xyz" ...
- Scratch少儿编程系列:(九)音乐高级技巧
一.程序说明 本程序用来演奏音乐,相对于“Scratch少儿编程系列:(八)演奏简单音乐”而言,本节介绍的方法适用于复杂点的音乐. 二.程序流程图 为了更直观的描述上述过程,采用流程图的方式将猜数字的 ...
- Java课堂疑问解答与思考4
一. 请运行以下示例代码StringPool.java,查看其输出结果.如何解释这样的输出结果?从中你能总结出什么? 答:定义的三个字符串如果相等,系统自动创建一个,并调用这个,对于由new创建的字符 ...
- ThinkPHP目录下面php文件 Access denied. 的问题
对于这种拒绝访问的报错,从我遇到过的问题总结来讲,可以从几个方向入手: 1. 文件权限. 最容易想到的也是这个 使用命令chmod -R 777 目录名 2. 环境配置. 这个我也是有遇到过的 ...
- 一个实用的iptables脚本(各种过滤写法参考)
#!/bin/shmodprobe ipt_MASQUERADEmodprobe ip_conntrack_ftpmodprobe ip_nat_ftpiptables -Fiptables -t n ...
- [FJOI2007]轮状病毒 题解(dp(找规律)+高精度)
[FJOI2007]轮状病毒 题解(dp(找规律)+高精度) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1335733 没什么好说的,直接把规律找出来,有 ...
- linux系统管理基础知识
1.linux的安装配置 虚拟机安装 Linux安装和分区 IP地址的配置 ifup eth0,ifdoen eth0 关闭不常用的程序 关闭selinux 远程登录(多用户,多任务) 用户和角色划分 ...