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的最小公倍数,然后做一 ...
随机推荐
- RuntimeError: Python is not installed as a framework.
RuntimeError: Python is not installed as a framework. 文章转载:https://www.cnblogs.com/harelion/p/563776 ...
- HDU - 1540 线段树的合并
这个题题意我大概解释一下,就是一开始一条直线,上面的点全是联通的,有三种操作 1.操作D把从左往右第x个村庄摧毁,然后断开两边的联通. 2.询问Q节点相联通的最长长度 3.把最后破坏的村庄重建. 这个 ...
- Karen and Coffee CodeForces - 816B (差分数组+预处理前缀和)
To stay woke and attentive during classes, Karen needs some coffee! Karen, a coffee aficionado, want ...
- Vladik and Complicated Book CodeForces - 811B (思维实现)
Vladik had started reading a complicated book about algorithms containing n pages. To improve unders ...
- java.lang.LinkageError: JAXB 2.0 API is being loaded from the bootstrap classloader
我的解决办法: 1.如果是application工程,则在程序中打印出 system.out.println(System.getProperty("java.endo ...
- 一些iptables配置
第一条是封堵22,80,8080端口的输出,第二条是为该ip的80端口设置输出白名单,亲测有效:第三条是禁止所有UDP报文的输出 iptables -I OUTPUT -p tcp -m multip ...
- Vector源码分析
Vector与ArrayList底层实现基本类似,底层都是用数组实现的,最大的不同是Vector是线程安全的.ArrayList源码分析请参考ArrayList源码分析 一.源码分析 基于jdk1.7 ...
- 【转】Linux下cp: omitting directory `XXX'问题解决
在linux系统中复制文件夹时提示如下: Shell代码 [root@idtp4 site-packages]# /site-packages/ cp: omitting directory ‘yag ...
- Mysql中的排序规则utf8_unicode_ci、utf8_general_ci总结
Mysql中utf8_general_ci与utf8_unicode_ci有什么区别呢?在编程语言中,通常用unicode对中文字符做处理,防止出现乱码,那么在MySQL里,为什么大家都使用utf8_ ...
- Windows10 等 administrator 打开IE 或者edge的方法
gpedit.msc 组策略处理即可