CodeForces 340E Iahub and Permutations 错排dp

Iahub and Permutations

题解:

令 cnt1 为可以没有限制位的填充数字个数。

令 cnt2 为有限制位的填充数字个数。

那么:对于cnt1来说, 他的值是cnt1!

然后我们对cnt2进行dp。

对于任意一个新加进来的数字,我们可以令一个一个没有限制位数放在这里, 那么新加进来的数字 ≈ 没有限制位, 他的方案为 i-1 * dp[i-1]

, 然后我们如果把这个数字放到有限制位的数来说, 那么他的转移方程就和错排一样了。

代码:

#include<bits/stdc++.h>
using namespace std;
#define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
#define LL long long
#define ULL unsigned LL
#define fi first
#define se second
#define pb push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lch(x) tr[x].son[0]
#define rch(x) tr[x].son[1]
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL _INF = 0xc0c0c0c0c0c0c0c0;
const LL mod =  (int)1e9+7;
const int N = 1e5 + 100;
LL dp[N];
int fvis[N];
int vis[N];
int cnt1, cnt2;
int main(){
    int n, t;
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i){
        scanf("%d", &t);
        if(t == -1) continue;
        vis[t] = 1;
        fvis[i] = 1;
    }
    for(int i = 1; i <= n; ++i){
        if(vis[i] + fvis[i] == 2) ;
        else if(!vis[i] && fvis[i]) cnt1++;
        else if(vis[i] + fvis[i] == 0) cnt2++;
    }
    dp[0] = 1;
//    cout << cnt1 << " " << cnt2 << endl;
    for(int i = 1; i <= cnt1; ++i) dp[0] = dp[0] * i % mod;
    for(int i = 1; i <= cnt2; ++i){
        dp[i] = cnt1 * dp[i-1] % mod + (i-1) * dp[i-1] % mod;
        if(i >= 2) dp[i] += (i-1) * dp[i-2] % mod;
        dp[i] %= mod;
//        cout << dp[i] << endl;
    }
    cout << dp[cnt2] << endl;
    return 0;
}

原文地址:https://www.cnblogs.com/MingSD/p/10859300.html

时间: 2024-10-09 20:33:25

CodeForces 340E Iahub and Permutations 错排dp的相关文章

codeforces 340E Iahub and Permutations(错排or容斥)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Iahub and Permutations Iahub is so happy about inventing bubble sort graphs that he's staying all day long at the office and writing permutations. Iahubina is angry that she is no more import

CodeForces 340E Iahub and Permutations

容斥原理,组合数. 找出有$cnt$个数字还有没放,那么总方案数就是$cnt!$. 总方案数里面包含了正确的和非正确的,我们需要将非正确的删去. 先删去$1$个数字$a[i]=i$的情况,发现会多删,要加回两个数字$a[i]=i$的情况,发现会多加......就是一个容斥原理的过程. #pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring>

hdu2068-RPG的错排-(dp递推式)

去年看错排公式,死都看不懂,基础扎实之后再来看就略懂了. 公式: dp[ n ] = ( n-1 ) * ( dp[n-1] + dp[n-2] ) 解析公式:比如有n个元素,各对应n个正确位置,dp[n]表示这n个元素全部排错的可能. 比如有元素:1 2 3 4 5 ... k ... n 1.假设第n个元素,要它在错误的位置上,则有n-1种情况. 2.对于剩下的n-1个元素,随便取一个位置上的元素k,要它在错误的位置上,则有2种情况 1)它在第n个元素的位置,相当于n和k两个元素交换位置,和

HDU 2068 RPG错排 错排公式

1.题意:1到N的序列的排列中,元素位置与元素值相对应的情况(值为i的元素在某个排列中正好排在第i个位置)大于等于序列规模一半的情况,有多少个? 2.输入输出:每组数据一个数,N,规定输入以0结尾: 3.分析:原题意换句话说,就是针对1到N的全排列,错排元素的个数小于等于N的情况有多少: 那么,输出即为:    ,其中F[i]表示1到i的错排方案数,后面一项为组合数,即选取i个错排: 这里推导一下错排公式,F[N]表示1到N的错排方案:第一步:选取N放到1到N-1之中任意一个位置,这样就有N-1

K - Wand(组合数+错排公式)

N wizards are attending a meeting. Everyone has his own magic wand. N magic wands was put in a line, numbered from 1 to n(Wand_i owned by wizard_i). After the meeting, n wizards will take a wand one by one in the order of 1 to n. A boring wizard deci

BZOJ 4517: [Sdoi2016]排列计数 错排+逆元

4517: [Sdoi2016]排列计数 Description 求有多少种长度为 n 的序列 A,满足以下条件: 1 ~ n 这 n 个数在序列中各出现了一次 若第 i 个数 A[i] 的值为 i,则称 i 是稳定的.序列恰好有 m 个数是稳定的 满足条件的序列可能很多,序列数对 10^9+7 取模. Input 第一行一个数 T,表示有 T 组数据. 接下来 T 行,每行两个整数 n.m. T=500000,n≤1000000,m≤1000000 Output 输出 T 行,每行一个数,表示

HDU 2048 错排

错排递推公式: d(n) = (n-1)*(d[n-1]+d[n-2]): 证明:将第n个元素放到第k处,第k处的元素如果放到第n处,就是d(n-2),否则,先假设放到第n处,然后错排,就是d(n-1): 1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 double fac[22] = {1,1}; 6 double d[22] = {0,0,1,2}; 7 8 int main() 9 { 10 for(int i=1;i<

错排问题

问题: 十本不同的书放在书架上.现重新摆放,使每本书都不在原来放的位置.有几种摆法? 这个问题推广一下,就是错排问题,是组合数学中的问题之一. 考虑一个有n个元素的排列,若一个排列中所有的元素都不在自己原来的位置上,那么这样的排列就称为原排列的一个错排. n个元素的错排数记为D(n). 研究一个排列错排个数的问题,叫做错排问题或称为更列问题. 错排问题最早被尼古拉·伯努利和欧拉研究,因此历史上也称为伯努利-欧拉的装错信封的问题.这个问题有许多具体的版本,如在写信时将n封信装到n个不同的信封里,有

lightoj 1095 - Arrange the Numbers (错排数)

题意: 求n个数的排列,前m个中有k个在自己的位置上的方法数. 思路: 设D[n]为n个元素的错排数. 于是我们有D[1] = 0 D[2] = 1: D[n] = (D[n-1] + D[n-2]) * (i-1) 考虑问题本身,我们首先从前m个数选k个数不动.即C(m,k).对于没有选的前m中的m-k个数肯定是参与了错排,而后面n-m个数中参加错排的个数不定,所以我们枚举一个后面n-m个数中选出i(0 <= i <= n - m)个数有没有参与错排.总共就有n-k-i参与了错排. 综上所述