传送门:QAQQAQ

题意:给你两个$1$~$n$的排列,0表示该位置数字不确定,两两交换第一个排列中的元素使之变成第二个排列,令$s[x]$表示对于所有不同的两个排列,最少交换次数为$x$的序列有$s[x]$个,求$x=0$~$n-1$所有的$s[i]$

思路:简直神题QAQ,不愧CF3400,思路十分巧妙

直接贴上大佬的题解:

  这里对于题解加上一些个人的理解:因为最少交换数就是$n-Cycle(G)$,所以我们可以统计不同连边情况对于环个数的贡献

  如果是数字单独成环,那么这个环仅有一个且不会变化,最后算进即可,如果数字成链,既不可能分成多个环,也不可能单独成环,最终肯定接在0-0两端,且只有一种情况,所以对答案不会有贡献

  那么剩下的就是统计$0-x$,$x-0$,$0-0$的组成不同个数环的方案数,用到第一类斯特林数(表示$i$个数摆成$j$个圆排列的方案个数,因为确定一个圆排列,0的值就可以确定了,即对应一种方案(除了$0-0$,两个接口都是0还要乘阶乘)),生成函数见上(用i表示i个环的方案数)

  ($x-0$接$0-x$必须要$0-0$过度,且$x-0$,$0-x$接进$0-0$对环的个数没有任何影响,因为开头结尾依然是$0-0$,且都是一条链,这些没有埋进去的才进行斯特林数统计)

  有一点要注意,就是$0-0$要乘$va!$,因为有$va$个$0-0$,圆排列即有$va$个接口,每个接口的数值都是随便的,所以要乘上阶乘;而一段有值接上时另一端点0就被赋值成了那个值,只有1种情况

代码:

#include<bits/stdc++.h>
using namespace std;
const int MOD=998244353;
const int N=5005; int ADD(int &x,int y)
{
x+=y;
if(x>=MOD) x%=MOD;
} int DEC(int &x,int y)
{
x=x+MOD-y;
if(x>=MOD) x-=MOD;
} int n,p[N],q[N];
int dp[N][N],C[N][N],base[N];
void init()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&p[i]);
for(int i=1;i<=n;i++) scanf("%d",&q[i]);
dp[0][0]=1;//(first stirling)
for(int i=1;i<=n;i++)
for(int j=0;j<=n;j++) dp[i][j]=(1LL*dp[i-1][j]*(i-1)+dp[i-1][j-1])%MOD;
C[0][0]=1;
for(int i=1;i<=n;i++)
{
C[i][0]=1;
for(int j=1;j<=n;j++) C[i][j]=(C[i-1][j]+C[i-1][j-1])%MOD;
}
base[0]=1;
for(int i=1;i<=n;i++) base[i]=1LL*base[i-1]*i%MOD;
} void run(int *a,int *b,int *c)
{
int ret[N*2];
memset(ret,0,sizeof(ret));//!!!
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++) ret[i+j]=(ret[i+j]+1LL*a[i]*b[j]%MOD)%MOD;
for(int i=0;i<=n;i++) c[i]=ret[i];
} //p->q
int va=0,vb=0,vc=0,vd=0;//0-0 0-x x-0 x-x
int bln[N],blp[N];//nxt/pre
int pre[N],nxt[N],vis[N];
int F[N*3],G[N*3],H[N*3];
void ready()
{
for(int i=1;i<=n;i++)
{
if(p[i]&&q[i]) nxt[p[i]]=q[i],pre[q[i]]=p[i];
else if(p[i]) bln[p[i]]=1;
else if(q[i]) blp[q[i]]=1;
else va++;
}
for(int i=1;i<=n;i++)//value
{
if(vis[i]) continue;
vis[i]=1;
int l=i,r=i;
while(!vis[pre[l]]&&pre[l]) l=pre[l],vis[l]=1;
while(!vis[nxt[r]]&&nxt[r]) r=nxt[r],vis[r]=1;
if(nxt[r]==l) vd++;
else if(blp[l]&&!bln[r]) vb++;
else if(!blp[l]&&bln[r]) vc++;
else if(blp[l]&&bln[r]) va++;
}
//cout<<va<<" "<<vb<<" "<<vc<<" "<<vd<<endl;
} int ans[N];
void solve()
{
int tmp;
for(int i=0;i<=vb;i++)
for(int j=i;j<=vb;j++)
{
if(j==vb) tmp=1;
else tmp=C[va+vb-j-1][va-1];//¿ÉÄÜva=0 µ½-1
ADD(G[i],1LL*dp[j][i]*C[vb][j]%MOD*tmp%MOD*base[vb-j]%MOD);
}
for(int i=0;i<=vc;i++)
for(int j=i;j<=vc;j++)
{
if(j==vc) tmp=1;
else tmp=C[va+vc-j-1][va-1];
ADD(H[i],1LL*dp[j][i]*C[vc][j]%MOD*tmp%MOD*base[vc-j]%MOD);
}
for(int i=0;i<=va;i++) ADD(F[i],1LL*dp[va][i]*base[va]%MOD);
run(F,G,F);
run(F,H,F);
for(int i=0;i<=va+vb+vc;i++) ans[n-i-vd]=F[i];
for(int i=0;i<n;i++) printf("%d ",ans[i]);
} int main()
{
init();
ready();
solve();
return 0;
}

CF715E—— Complete the Permutations的更多相关文章

  1. CF715E Complete the Permutations(第一类斯特林数)

    题目 CF715E Complete the Permutations 做法 先考虑无\(0\)排列的最小花费,其实就是沿着置换交换,花费:\(n-\)环个数,所以我们主要是要求出规定环的个数 考虑连 ...

  2. 【CF715E】Complete the Permutations(容斥,第一类斯特林数)

    [CF715E]Complete the Permutations(容斥,第一类斯特林数) 题面 CF 洛谷 给定两个排列\(p,q\),但是其中有些位置未知,用\(0\)表示. 现在让你补全两个排列 ...

  3. CF 715 E. Complete the Permutations

    CF 715 E. Complete the Permutations 题目大意:给定两个排列\(p,q\)的一部分.定义两个排列\(p,q\)的距离为使用最少的交换次数使得\(p_i=q_i\).对 ...

  4. 【CF715E】Complete the Permutations 第一类斯特林数

    题目大意 有两个排列 \(p,q\),其中有一些位置是空的. 你要补全这两个排列. 定义 \(s(p,q)\) 为 每次交换 \(p\) 中的两个数,让 \(p=q\) 的最小操作次数. 求 \(s( ...

  5. @codeforces - 715E@ Complete the Permutations

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定两个排列 p, q,他们中的有些位置被替换成了 0. 两个排 ...

  6. Codeforces 715E - Complete the Permutations(第一类斯特林数)

    Codeforces 题面传送门 & 洛谷题面传送门 神仙题.在 AC 此题之前,此题已经在我的任务计划中躺了 5 个月的灰了. 首先考虑这个最短距离是什么东西,有点常识的人(大雾)应该知道, ...

  7. python常用算法(7)——动态规划,回溯法

    引言:从斐波那契数列看动态规划 斐波那契数列:Fn = Fn-1 + Fn-2    ( n = 1,2     fib(1) = fib(2) = 1) 练习:使用递归和非递归的方法来求解斐波那契数 ...

  8. Solution Set - Stirling 数相关杂题

      <好多题的题解>   「洛谷 P5408」第一类斯特林数·行   根据结论 \[x^{\overline{n}}=\sum_i{n\brack i}x^i, \] 我们只需要求出 \( ...

  9. Permutations II

    Given a collection of numbers that might contain duplicates, return all possible unique permutations ...

随机推荐

  1. OAth 2.0 的白话讲解

    一.OAuth2.0是什么,主要做什么用的? 官方注解 简单说,OAuth 就是一种授权机制.数据的所有者告诉系统,同意授权第三方应用进入系统,获取这些数据.系统从而产生一个短期的进入令牌(token ...

  2. linux的pci驱动模型

    做个笔记 linux通过pcibios_scan_root函数以深度优先的算法搜索整个pci架构,建立一个树形的链表,如下: 之后再调用pci_bus_add_devices函数把所有搜索到的pci_ ...

  3. MeteoInfoLab脚本示例:subplot

    subplot命令可以自动等间距分配多个坐标系(Axes),命令中有三个参数,前两个定义了行数和列数,第三个指定了当前的坐标系(Axes),绘图命令是作用在当前坐标系中的. 脚本程序: def f(t ...

  4. 工业级wifi模块

    工业级wifi模块 工业级wifi模块ZLSN7004是上海卓岚开发的一款高性能的Wifi.以太网转串口模块.与普通的wifi模块定位在低成本不同,7004定位在高稳定性.丰富功能,设计目标是面向对功 ...

  5. day05 Pyhton学习总结

    1.字符串str s1="asasd",字符串不能修改 修改以后只能赋值给另一个变量 ret1=s1 1.切片 s1[0], s1[-1], s1[2:4], s1[-1:-4:- ...

  6. js、css等文件引入空白问题

    路径没错,不管路径怎么改变,js.css等文件就是引入失败.很多时候是因为Spring的过滤器把js.css等资源文件拦截了.default是tomcat配置的一个servlet,"Defa ...

  7. ASP.NET 获取客户端IP地址

    我们用Request.ServerVariables( "REMOTE_ADDR ")   来取得客户端的IP地址, 但如果客户端是使用代理服务器来访问,那取到的就是代理服务器的I ...

  8. 第十二章 LNMP架构之分离数据库

    一.课程回顾 1.搭建LNMP环境 1.配置官方源2.yum安装依赖3.yum安装nginx4.配置nginx5.创建用户6.启动并加入开机自启​7.上传安装包8.解压安装包9.卸载旧版本PHP10. ...

  9. wifi - 无线相关命令

    1.Linux环境下的无线相关操作命令 interface 指代当前网卡 一般是 wifi0 ,  eth0 ,  ath1等 ifconfig - 常用查看网络设定及控制网卡(Windows下是ip ...

  10. 【应用服务 App Service】快速获取DUMP文件(App Service for Windows(.NET/.NET Core))

    问题情形 当应用在Azure 应用服务App Service中运行时,有时候出现CPU,Memory很高,但是没有明显的5XX错误和异常日志,有时就是有异常但是也不能明确的指出具体的代码错误.当面临这 ...