题面传送门

一道挺有意思的题罢……

首先看到这种与置换乘法相关的题,首先把这些置换拆成一个个置换环,假设输入的置换有 \(m\) 个置换环,大小分别为 \(s_1,s_2,\cdots,s_m\),显然置换环与置换环的顺序是不影响的,因此我们只用考虑它的大小即可。

其次我们考虑对于一个置换,我们来考虑对其进行 \(k\) 次幂后会得到什么。手玩几组数据就可以发现,原来不在同一个置换环中的元素,进行 \(k\) 次幂后,肯定也不会在同一个置换环中,而有的原本在同一个置换环中的元素进行 \(k\) 次幂后会被拆开,具体来说,对于一个大小为 \(s\) 的置换环,进行 \(k\) 次幂后会拆成 \(\gcd(s,k)\) 个等大小的置换环,道理很明白,对于一个元素,你每次绕着置换环走 \(k\) 步,显然 \(\dfrac{s}{\gcd(s,k)}\) 次就会回到源点,因此 \(k\) 次幂后拆出的置换环中,单个置换环大小就是 \(\dfrac{s}{\gcd(s,k)}\)。

也就是说 \(s_1,s_2,\cdots,s_m\) 中有一些大小相同的置换环能拼起来,显然不同大小的置换环的方案数是独立的,因此我们可以分别求出每个大小的置换环拼起来的方案数再用乘法原理乘起来。考虑设 \(c_i\) 表示大小为 \(i\) 的置换环有多少个,那么根据之前的结论 \(j\) 个大小为 \(i\) 的置换环能够拼起来当且仅当 \(\gcd(ij,k)=j\)。那么怎么求大小为 \(i\) 的置换环拼起来有多少种方案呢?这时候就要用到 \(dp\) 了,我们设 \(dp_j\) 表示用了 \(j\) 个大小为 \(i\) 的置换环的方案数,考虑转移,我们枚举第 \(j\) 个大小为 \(i\) 的置换环跟多少个环在一起拼成大环,假设为 \(r\) 个,那么 \(dp_i=\sum\limits_rdp_{i-r}\dbinom{i-1}{r-1}f(r,i)[\gcd(ir,k)=r]\),其中 \(f(r,i)\) 表示将 \(r\) 个大小为 \(i\) 的置换环拼起来的方案数,注意到 \(\gcd(ir,k)=r\Rightarrow r\mid k\),因此枚举的 \(r\) 必须是 \(k\) 的约数,又 \(\sum c_i=m\) 是 \(\mathcal O(n)\) 级别的,因此这样暴力 DP 总枚举量是 \(n·d(k)\) 的。

最后考虑怎样求 \(f(r,i)\),由于最后拼成的是一个环,因此我们钦定第一个环的第一个元素必须在第一个位置,否则会算重,将剩余 \(r-1\) 个环填入剩余 \(r-1\) 个位置有 \((r-1)!\) 种,剩余 \((r-1)!\) 个环也可自由旋转,方案数为 \(i^{r-1}\),因此 \(f(r,i)=(r-1)!\times i^{r-1}\),随便算算即可。

时间复杂度 \(n·d(k)·\log n\),因为计算 \(f(r,i)\) 时涉及快速幂。

const int MAXN=1e5;
const int MOD=998244353;
int n,p[MAXN+5],c[MAXN+5],dp[MAXN+5],vis[MAXN+5];
int fac[MAXN+5],ifac[MAXN+5];vector<int> f;
int gcd(int x,int y){return (!y)?x:gcd(y,x%y);}
int qpow(int x,int e){
int ret=1;
for(;e;e>>=1,x=1ll*x*x%MOD) if(e&1) ret=1ll*ret*x%MOD;
return ret;
}
void init_fac(int n){
for(int i=(fac[0]=ifac[0]=ifac[1]=1)+1;i<=n;i++) ifac[i]=1ll*ifac[MOD%i]*(MOD-MOD/i)%MOD;
for(int i=1;i<=n;i++) fac[i]=1ll*fac[i-1]*i%MOD,ifac[i]=1ll*ifac[i-1]*ifac[i]%MOD;
}
int binom(int n,int k){return 1ll*fac[n]*ifac[k]%MOD*ifac[n-k]%MOD;}
int main(){
scanf("%d",&n);init_fac(n);int ans=1;
for(int i=1;i<=n;i++) scanf("%d",&p[i]);
for(int i=1;i<=n;i++) if(n%i==0) f.pb(i);
for(int i=1;i<=n;i++) if(!vis[i]){
int siz=0;for(int j=i;!vis[j];j=p[j]) vis[j]=1,siz++;
c[siz]++;
}
for(int i=1;i<=n;i++){
dp[0]=1;
for(int j=1;j<=c[i];j++){
dp[j]=0;
for(int k=0;k<f.size()&&f[k]<=j&&i*f[k]<=n;k++)
if(gcd(i*f[k],n)==f[k]){
dp[j]=(dp[j]+1ll*dp[j-f[k]]*binom(j-1,f[k]-1)%MOD*
fac[f[k]-1]%MOD*qpow(i,f[k]-1))%MOD;
}
} ans=1ll*ans*dp[c[i]]%MOD;
} printf("%d\n",ans);
return 0;
}

洛谷 P4709 - 信息传递(置换+dp)的更多相关文章

  1. 洛谷P2661 信息传递(最小环,并查集)

    洛谷P2661 信息传递 最小环求解采用并查集求最小环. 只适用于本题的情况.对于新加可以使得两个子树合并的边,总有其中一点为其中一棵子树的根. 复杂度 \(O(n)\) . #include< ...

  2. [NOIP2015] 提高组 洛谷P2661 信息传递

    题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知道自己的生日.之后每一 ...

  3. 洛谷 P2661 信息传递 Label:并查集||强联通分量

    题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知道自己的生日.之后每一 ...

  4. 洛谷P2661 信息传递==coedevs4511 信息传递 NOIP2015 day1 T2

    P2661 信息传递 题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知 ...

  5. 洛谷 P2661 信息传递(并查集 & 最小环)

    嗯... 题目链接:https://www.luogu.org/problemnew/show/P2661 这道题和一些比较水的并查集不太一样,这道题的思路就是用并查集来求最小环... 首先,如果我们 ...

  6. NOIP2015提高组T2 洛谷P2661 信息传递

    题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知道自己的生日.之后每一 ...

  7. 洛谷——P2661 信息传递

    https://www.luogu.org/problem/show?pid=2661#sub 题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其 ...

  8. 洛谷 P2661 信息传递 题解

    P2661 信息传递 题目描述 有 \(n\) 个同学(编号为 \(1\) 到 \(n\) )正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为 \(i\) 的同学的信息传 ...

  9. 洛谷p2661信息传递题解

    题目 这个题一眼看上去就是用并查集求最小环. 我们可以设两个数组分别是f,d分别表示该点的爸爸和该点到祖先的距离. 当该点的爸爸等于他时,那他肯定就是祖先. 此时信息就肯定传递完了,此时的整个图中(我 ...

随机推荐

  1. 生产环境全链路压测平台 Takin

    什么是Takin? Takin是基于Java的开源系统,可以在无业务代码侵入的情况下,嵌入到各个应用程序节点,实现生产环境的全链路性能测试,适用于复杂的微服务架构系统. Takin核心原理图 Taki ...

  2. 性能利器 Takin 来了!首个生产环境全链路压测平台正式开源

    6 月 25 日,国内知名的系统高可用专家数列科技宣布开源旗下核心产品能力,对外开放生产全链路压测平台产品的源代码,并正式命名为 Takin. 目前中国人寿.顺丰科技.希音.中通快递.中国移动.永辉超 ...

  3. 吴恩达深度学习课后习题第5课第1周第3小节: Jazz Improvisation with LSTM

    目录 Improvise a Jazz Solo with an LSTM Network Packages 1 - Problem Statement 1.1 - Dataset What are ...

  4. relativeLayout相对布局的嵌套在py中的引用

    from kivy.app import App from kivy.uix.button import Button from kivy.uix.relativelayout import Rela ...

  5. Java:创建对象小记

    Java:创建对象小记 对 Java 中的创建对象的内容,做一个微不足道的小小小小记 创建对象的方式概述 使用 new 关键字:Person person = new Person(); 反射创建:使 ...

  6. [no code][scrum meeting] Alpha 12

    项目 内容 会议时间 2020-04-19 会议主题 周总结会议 会议时长 45min 参会人员 全体成员 $( "#cnblogs_post_body" ).catalog() ...

  7. Vue3+Typescript+Node.js实现微信端公众号H5支付(JSAPI v3)教程--各种填坑

    ----微信支付文档,不得不说,挺乱!(吐槽截止) 功能背景 微信公众号中,点击菜单或者扫码,打开公众号中的H5页面,进行支付. 一.技术栈 前端:Vue:3.0.0,typescript:3.9.3 ...

  8. python +spatialite + window 解决方案(https://www.jianshu.com/p/5bc7d8b7b429)

    运行环境在windows 10 64bit.先将python安装完成.然后,到 spatilite官网 找到MS(即Microsoft)版本,下载64位的mod_spatialite,将其先解压到目标 ...

  9. Linux 系统 Oracle 11g 修改监听端口

    1.查看监听:lsnrctl status 2.停止监听:lsnrctl stop 3.修改oracle安装目录的下的配置文件listener.ora:一般路径为自己Oracle安装目录+/app/o ...

  10. Springboot第一次访问慢,自身缺陷问题?

    一.现象: 1.访问controller,第一次速度在300-400ms,第二次访问就很快了大概在20ms,相差几十倍,是哪里出了问题,尝试了网上很多教程都没有作用 如启动参数设置 -Djava.se ...