BZOJ4517:排列计数(错排公式)

2023-10-19 16:50

本文主要是介绍BZOJ4517:排列计数(错排公式),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

从开始看这题到现在,已经过了30多把lol的时间了。
话说今天又有一道排列计数的题让我懵逼。

题面
题意:问有多少长为n的排列a,恰好有m个位置存在a[i]=i。

我们枚举这n-m个a[i]≠i位置,有 Cmn 种情况。
对于x个数的排列,不存在a[i]=i的方案数设为f[x]。经过简单的打表可以发现

f[i]=f[i1]i+(1)i

就可以水出这题了。

但是像千反田一样好奇的我非常好奇,学习了一下机巧的二项式反演。
我曾听说过广义容斥原理
讲的是对于一个含有n个条件的集合,全集为P。f[i]为恰好满足i个条件的方案数,w[S]为满足集合S中条件的方案数,g[S]为S的元素个数。公式为

f[r]=SP(1)g[S]rCrg[S]w[S]

我们设
h[x]=g[S]=xw[S]

就有
f[r]=i=rn(1)irCrih[i]

再回想h的计算方法,有
h[r]=i=rnCrif[i]f[r]=i=rn(1)irCrih[i]

变形一下(我并不懂怎么变形,但每条柿子我都会证明),有
h[r]=i=0rCirf[i]f[r]=i=0r(1)riCirh[i]

再有
h[r]=i=0r(1)iCirf[i]f[r]=i=0r(1)iCirh[i]

证一下最后一条吧
i=0r(1)iCirf[i]

=i=0r(1)iCirj=0i(1)jCjih[j]

=i=0rj=0i(1)i(1)jCirCjih[j]

=i=0rj=0i(1)ijCjrCijrjh[j]

=j=0rCjrh[j]i=jr(1)ijCijrj

由于对于杨辉三角的每一行,奇数项之和等于偶数项之和,故
=f[r]

有n个集合,假若设任意i个集合的并集大小都为f[i],任意i个集合的补集的并集的大小都为h[i](不知道这样的集合存不存在),就有

h[r]=i=0r(1)iCirf[i]
f[r]=i=0r(1)iCirh[i]

对于错排,设f[i]为i个数错排的方案。
显然有

i=0nCinf[i]=n!

反演过来就有
f[n]=i=0n(1)niCini!

=n!i=0n(1)ii!

终于打完了,嘟嘟噜。

#include <iostream>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <cstring>using namespace std;
#define mmst(a, b) memset(a, b, sizeof(a))
#define mmcp(a, b) memcpy(a, b, sizeof(b))typedef long long LL;const int nn=1000000,N=1003000;
const int p=1e9+7;int T,n,m;
LL jc[N],Ijc[N],I[N],f[N];int main()
{jc[0]=Ijc[0]=I[1]=1;for(int i=2;i<=nn;i++)I[i]=(p-p/i)*I[p%i]%p;for(int i=1;i<=nn;i++)jc[i]=jc[i-1]*i%p;for(int i=1;i<=nn;i++)Ijc[i]=Ijc[i-1]*I[i]%p;f[0]=1;f[1]=0;for(int i=2;i<=nn;i++)if(i&1)f[i]=(f[i-1]*i-1+p)%p;elsef[i]=(f[i-1]*i+1)%p;cin>>T;while(T--){scanf("%d%d",&n,&m);LL ans=jc[n]*Ijc[m]%p*Ijc[n-m]%p*f[n-m]%p;printf("%lld\n",ans);}return 0;
}

这里写图片描述
还是纱雾的水题专场

这篇关于BZOJ4517:排列计数(错排公式)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/241095

相关文章

hdu 4565 推倒公式+矩阵快速幂

题意 求下式的值: Sn=⌈ (a+b√)n⌉%m S_n = \lceil\ (a + \sqrt{b}) ^ n \rceil\% m 其中: 0<a,m<215 0< a, m < 2^{15} 0<b,n<231 0 < b, n < 2^{31} (a−1)2<b<a2 (a-1)^2< b < a^2 解析 令: An=(a+b√)n A_n = (a +

PHP字符串全排列

方法一: $str = 'abc';$a =str_split($str);perm($a, 0, count($a)-1);function perm(&$ar, $k, $m) {if($k == $m){ echo join('',$ar), PHP_EOL;}else {for($i=$k; $i<=$m; $i++) {swap($ar[$k], $ar[$i]);perm($ar

回溯——9.全排列

力扣题目链接 给定一个 没有重复 数字的序列,返回其所有可能的全排列。 示例: 输入: [1,2,3]输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ] 解题思路 问题建模:题目要求给出一个数组的所有排列组合,属于典型的全排列问题,这可以用回溯法来解决。回溯法通过递归的方式,依次将数组中的每个元素放入排列中,直到生成

YOLOv8/v10+DeepSORT多目标车辆跟踪(车辆检测/跟踪/车辆计数/测速/禁停区域/绘制进出线/绘制禁停区域/车道车辆统计)

01:YOLOv8 + DeepSort 车辆跟踪 该项目利用YOLOv8作为目标检测模型,DeepSort用于多目标跟踪。YOLOv8负责从视频帧中检测出车辆的位置,而DeepSort则负责关联这些检测结果,从而实现车辆的持续跟踪。这种组合使得系统能够在视频流中准确地识别并跟随特定车辆。 02:YOLOv8 + DeepSort 车辆跟踪 + 任意绘制进出线 在此基础上增加了用户

二维旋转公式

二维旋转公式 ros的tf工具包可以很方便的实现任意坐标系之间的坐标转换。但是,如果只是想简单的测试想法,而又不想编写过于庞杂的代码,考虑自己写二维旋转的函数。而与二维旋转问题对偶的另一个问题便是二维坐标系旋转变换。这两个问题的形式基本一样,只是旋转的角度相差一个负号。就是这个容易搞混,所以做个笔记,以备查用。 1. 二维旋转公式(算法) 而(此文只针对二维)旋转则是表示某一坐标点 ( x

word转PDF后mathtype公式乱码以及图片分辨率降低等一系列问题|完美解决

word转PDF后mathtype公式乱码以及图片分辨率降低等一系列问题|完美解决 问题描述 最近在投一篇期刊论文,直接提交word文档,当时没有查看提交预览,一审审稿意见全是:公式乱码、公式乱码、乱码啊!!!是我大意了,第二次提交,我就决定将word文档转成PDF后再提交,避免再次出现公式乱码的问题。接着问题又来了,我利用‘文件/导出’或‘文件/另存为’的方式将word转成PDF后,发现公式

代码随想录刷题day25丨491.递增子序列 ,46.全排列 ,47.全排列 II

代码随想录刷题day25丨491.递增子序列 ,46.全排列 ,47.全排列 II 1.题目 1.1递增子序列 题目链接:491. 非递减子序列 - 力扣(LeetCode) 视频讲解:回溯算法精讲,树层去重与树枝去重 | LeetCode:491.递增子序列_哔哩哔哩_bilibili 文档讲解:https://programmercarl.com/0491.%E9%80%92%E

归并排序/计数排序

1:归并排序 1.1:代码 void _MergeSort(int* arr, int left, int right, int* tmp){if (left >= right){return;}int mid = (left + right) / 2; _MergeSort(arr, left, mid, tmp); _MergeSort(arr, mid+1, righ

牛客小白月赛100(A,B,C,D,E,F三元环计数)

比赛链接 官方讲解 这场比较简单,ABC都很签到,D是个不太裸需要预处理的 B F S BFS BFS 搜索,E是调和级数暴力枚举,F是三元环计数。三元环考的比较少,没见过可能会偏难。 A ACM中的A题 思路: 就是枚举每个边变成原来的两倍,然后看看两短边之和是否大于第三边即可。 不能只给最短边乘 2 2 2,比如 1 4 8 这组数据,也不能只给第二短边乘 2 2 2,比

python 实现第k个字典排列算法

第k个字典排列算法介绍 "第k个字典排列"算法通常指的是在给定的字符集合(例如,字符串中的字符)中,找到所有可能排列的第k个排列。这个问题可以通过多种方法解决,但一个常见且高效的方法是使用“下一个排列”算法的变种,或称为“第k个排列”的直接算法。 方法一:使用“下一个排列”的变种 生成所有排列:首先生成所有排列,但显然这种方法对于较大的输入集合是不切实际的,因为它涉及到大量的计算和存储。 排序