【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 多项式乘法 ...
随机推荐
- UI-WPF_UI:WPF UI - DMSkin官方网站
ylbtech-UI-WPF_UI:WPF UI - DMSkin官方网站 1.返回顶部 1. QQ: 944095635 DMSkin.com 首页 论坛 定制 博客 联系 DMSkin 3. ...
- 测开之路一百四十三:ORM框架之SQLAlchemy模型及表创建
基于前一篇内容,可以使用模型的结构 目录结构 main,入口层 from flask import Flaskfrom flask_sqlalchemy import SQLAlchemy app = ...
- Selenium学习之==>Selenium介绍
前世 Selenium RC 早期的Selenium使用的是JavaScript注入技术与浏览器打交道,需要Selenium RC启动一个Server,将操作Web元素的API调用转化为一段段Java ...
- 【ABAP系列】SAP ABAP系统变量及注释
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP系统变量及注释 ...
- C#中的委托和事件(一)——delegate
前言 来说一说委托(delegate)和事件(event),本篇采取的形式是翻译微软Delegate的docs中的重要部分(不要问我为什么微软的docs有中文还要读英文,因为读中文感觉自己有阅读障碍- ...
- 背包dp相关
0/1背包 给出n个物品,每个物品有Vi的价值和Wi的费用,我们总共有m块钱,求最多能得到多少价值的物品. N<=10^3,m<=10^3 记录方案数?记录输出方案? 输出方案: 对每个d ...
- 使用redis+flask维护动态代理池
在进行网络爬虫时,会经常有封ip的现象.可以使用代理池来进行代理ip的处理. 代理池的要求:多站抓取,异步检测.定时筛选,持续更新.提供接口,易于提取. 代理池架构:获取器,过滤器,代理队列,定时检测 ...
- HNUSTOJ-1257 You are my brother
1257: You are my brother 时间限制: 1 Sec 内存限制: 128 MB提交: 39 解决: 15[提交][状态][讨论版] 题目描述 Little A gets to ...
- asp.net table表格表头及列固定实现
http://blog.csdn.net/zdw_wym/article/details/48630337 在开发中常会遇到table表格中列特别多,下拉后,表头就看不见了,水平滚动后,第1.2列就看 ...
- 从零开始配置安装Flutter开发环境
flutter 中文网 https://flutterchina.club/get-started/install/ 1.配置全局环境 PUB_HOSTED_URL=https://pub.flutt ...