zoukankan      html  css  js  c++  java
  • Iahub and Permutations(codeforces 314c)

    题意:给出一组排列,某些位置不知道(-1),要求求出有多少种还原方式,使得所有a[i]!=i 

    /*
      这是一道关于排列的动态规划,这种体大都可以当作棋盘来做,如果把i这个数放到第j个位置,那么就将棋盘的第i行第j列填入数字,最后使每一行每一列只有一个数。 
      我们从棋盘中删去已经填入数字的行和列,设删完后的棋盘为nn*nn,设mm为不能填数的位置数,f[i][j]代表i*i的棋盘有j个不能填数的位置的合法方案。 
      转移方程:f[i][j]=f[i][j-1]-f[i-1][j-1] 边界:f[i][0]=i!
      转移方程的含义:相比f[i][j-1],f[i][j]多了一个不能填数的位置,而这个位置填数的方案数为f[i-1][j-1] 
    */
    #include<cstdio>
    #include<iostream>
    #define N 2010
    #define mod 1000000007
    using namespace std;
    int vish[N],visl[N],jc[N],n,nn,mm;
    long long f[N][N];
    int main(){
        scanf("%d",&n);nn=n;
        for(int i=1;i<=n;i++){
            int x;scanf("%d",&x);
            //if(i==x){printf("0");return 0;} //不知道是我读错了题目还是怎么着,加上这句就不对了 
            if(x!=-1){vish[x]=1;visl[i]=1;nn--;}
        }
        for(int i=1;i<=n;i++)if(!vish[i]&&!visl[i])mm++;
        long long p=1;f[0][0]=1;
        for(int i=1;i<=nn;i++)p*=i,p%=mod,f[i][0]=p;//刚开始没开long long,然后就炸了 
        for(int i=1;i<=nn;i++)
            for(int j=1;j<=mm;j++){
                f[i][j]=f[i][j-1]-f[i-1][j-1];
                f[i][j]=((f[i][j]%mod)+mod)%mod;
            }
        printf("%d",f[nn][mm]);
        return 0;
    }
  • 相关阅读:
    小波变换的引入,通俗易懂
    Leetcode 437. Path Sum III
    Leetcode 113. Path Sum II
    Leetcode 112 Path Sum
    Leetcode 520 Detect Capital
    Leetcode 443 String Compression
    Leetcode 38 Count and Say
    python中的生成器(generator)总结
    python的random模块及加权随机算法的python实现
    leetcode 24. Swap Nodes in Pairs(链表)
  • 原文地址:https://www.cnblogs.com/harden/p/6391993.html
Copyright © 2011-2022 走看看