Codeforces340 E. Iahub and Permutations
出处: Codeforces
主要算法:思维+DP
难度:4.8
题意:
有一个长度为$n$的排列(即各元素互不相同),其中有一些为-1。现要求将数填到这些-1上,使得原排列是一个错位排列。问有几种方法?
思路分析:
又是一道超级难的DP……
这不就是一个错排的模板题吗?不是只要看有几个-1就做多少的错排吗?确实,样例很不良心,那就给你一组反例吧……
5
-1 -1 2 3 -1
我们注意到了,并不是剩下的元素全是错排。因为原来我们认为2不能处在2的位置,但是4作为第二个元素是可以处在2的位置的。这样一来……就错得很离谱了。
但是这道题跟错排的关系依然是很大的。如果还不了解错排,可以参见我的另一篇博客「错位排列及有关例题」
我们首先可以根据数字是否为-1,以及数字i是否被使用过,把给的数字$a[i]$分成几类:
第一类,$a[i] = -1$ 且 数字$i$还没有被使用过(即数字$i$没有出现在给定的序列中),那么这个位置除了其位置本身对应的数字$i$以外,其他剩余的数字都可以填进来。
第二类,$a[i] = -1$ 且 数字$i$已经被使用过了,那么任何剩余的数字都可以填进来而且不会影响错位排列,想填什么就填什么。
第三类,$a[i] ≠ -1$ 且 数字$i$还没有被使用过,这种数字的个数应该和第一类相同,都是有限制的随便填。
第四类,$a[i] ≠ -1$ 且 数字$i$已经被使用过了,这种东西用都没有,就当他们是垃圾就好了。
首先我们可以统计出一类(或三类)数字的出现次数$y$,以及二类数字的出现次数$x$。我们只考虑二类数字可能组成的方案数,将有$x$个数字填到$x$个无限制的位置中,方案数就是$P_x^x$。
下面正式开始DP。令$f[i]$表示加入$i$个一类数字后的方案数。因此很容易得到$f[0] = P_x^x,即 x!$
下面开始状态转移。对于第$i$个一类数字,我们可以把他填入到无限制的二类数字的位置中,方案数是$x * f[i-1]$。剩余的就直接做错位排列即可。
代码注意点:
随手MOD
Code
/*By QiXingzhi*/
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#define r read()
#define Max(a,b) (((a)>(b)) ? (a) : (b))
#define Min(a,b) (((a)<(b)) ? (a) : (b))
using namespace std;
typedef long long ll;
#define int ll
const int N = ;
const int INF = ;
const int MOD = ;
inline int read(){
int x = ; int w = ; register int c = getchar();
while(c ^ '-' && (c < '' || c > '')) c = getchar();
if(c == '-') w = -, c = getchar();
while(c >= '' && c <= '') x = (x << ) +(x << ) + c - '', c = getchar();
return x * w;
}
int n,ans,x,y;
int f[N],a[N],b[N];
inline int JieCheng(int x){
int res = ;
for(int i = ; i <= x; ++i){
res = (res * i) % MOD;
}
return res%MOD;
}
#undef int
int main(){
#define int ll
// freopen(".in","r",stdin);
n = r;
for(int i = ; i <= n; ++i){
a[i] = r;
if(a[i] != -){
b[a[i]] = ;
}
}
// for(int i = 1; i <= n; ++i){
// printf("%lld ",b[i]);
// }
for(int i = ; i <= n; ++i){
if(a[i] == - && b[i] > ){
++x;
}
// printf("a[%lld] = %lld b[%lld] = %lld\n",i,a[i],i,b[i]);
if(a[i] == - && b[i] == ){
++y;
}
}
// printf("x = %lld y = %lld\n",x,y);
f[] = JieCheng(x);
for(int i = ; i <= y; ++i){
f[i] = (x * f[i-] + (i-) * f[i-]) % MOD;
if(i > ) f[i] = (f[i] + (i-) * f[i-]) % MOD;
}
printf("%lld",f[y]);
return ;
}
Codeforces340 E. Iahub and Permutations的更多相关文章
- codeforces 341C Iahub and Permutations(组合数dp)
C. Iahub and Permutations time limit per test 1 second memory limit per test 256 megabytes input sta ...
- codeforces 340E Iahub and Permutations(错排or容斥)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud Iahub and Permutations Iahub is so happy ...
- cf-341C Iahub and Permutations
C. Iahub and Permutations time limit per test 1 second memory limit per test 256 megabytes input sta ...
- Codeforces Round #198 (Div. 2) E. Iahub and Permutations —— 容斥原理
题目链接:http://codeforces.com/contest/340/problem/E E. Iahub and Permutations time limit per test 1 sec ...
- CodeForces 340E Iahub and Permutations 错排dp
Iahub and Permutations 题解: 令 cnt1 为可以没有限制位的填充数字个数. 令 cnt2 为有限制位的填充数字个数. 那么:对于cnt1来说, 他的值是cnt1! 然后我们对 ...
- CodeForces 340E Iahub and Permutations
容斥原理,组合数. 找出有$cnt$个数字还有没放,那么总方案数就是$cnt!$. 总方案数里面包含了正确的和非正确的,我们需要将非正确的删去. 先删去$1$个数字$a[i]=i$的情况,发现会多删, ...
- CF341C. Iahub and Permutations [DP 排列]
http://codeforces.com/contest/341/problem/C 题意: 有一个长度为n的排列a,其中有一些位置被替换成了-1.你需要尝试恢复这个排列,将-1替换回数字.求有多少 ...
- Iahub and Permutations(codeforces 314c)
题意:给出一组排列,某些位置不知道(-1),要求求出有多少种还原方式,使得所有a[i]!=i /* 这是一道关于排列的动态规划,这种体大都可以当作棋盘来做,如果把i这个数放到第j个位置,那么就将棋盘的 ...
- Codeforces Round #198 (Div. 2)
A.The Wall 题意:两个人粉刷墙壁,甲从粉刷标号为x,2x,3x...的小块乙粉刷标号为y,2y,3y...的小块问在某个区间内被重复粉刷的小块的个数. 分析:求出x和y的最小公倍数,然后做一 ...
随机推荐
- 编剧小记 — Contour
前言 Contour 是一款比较优秀的编剧辅助软件,按理说这篇文章应该归类到mac小记中,但其操作非常简单,基本上以写作提示为主.只怪所有提示都是英语,而且很多,每次使用打开 Contour 个别单词 ...
- python爬虫随笔-scrapy框架(1)——scrapy框架的安装和结构介绍
scrapy框架简介 Scrapy,Python开发的一个快速.高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据.Scrapy用途广泛,可以用于数据挖掘.监测和自动化测试 ...
- 第十五次oo作业
作业十五 测试与正确性论证的效果差异 程序的测试需要通过输入特定数据等方式,检查程序是否和预期相同,因为测试不可能穷举,导致了不穷举的测试不可能验证程序是完全正确的,只能验证程序在测试时没有发生错误, ...
- Random()种子数
Random rand =new Random(25); int i; i=rand.nextInt(100); 初始化时25并没有起直接作用,rand.nextInt(100);中的100是随机数的 ...
- MyEclipse和eclipse的区别
对于新手来说,MyEclipse和eclipse来说的区别可能就是MyEclipse比eclipse多了my,MyEclipse主要为JavaEE开发,而Eclipse主要为Java开发..那么MyE ...
- jQuery中.html(“xxx”)和.append("xxx")有什么区别
append是追加,html是完全替换比如<p id="1"><p>123</p></p>$("#1").htm ...
- CodeIgniter框架中尝试使用swoole
ci框架版本:3.1.7. swoole版本:1.7. php版本:5.6 相关文档: 以cli方式运行ci框架 swoole官方手册 创建一个TestSwoole和Hello控制器 ...
- windows下使用cmake编译zlib与libpng libjpeg
win7下使用VS2010编译jpeglib 1.下载源代码下载地址:http://www.ijg.org/files/, 选择最新版本的windows版本压缩包,进行下载. jpeg ...
- Excel文件读取的两种方式
1.Pandas库的读取操作 from pandas import read_excel dr=read_excel(filename,header) dr#dataframe数据 dw=DataFr ...
- Django--CRM--QueryDict, 模糊搜索, 加行级锁
一 . QueryDict的修改 # QueryDict正常是不允许修改的,要想往里面添加内容,需要另mutable=True dic = request.GET print(dic) # <Q ...