codeforces 341C Iahub and Permutations(組合數dp)

來源:互聯網
上載者:User

C. Iahub and Permutationstime limit per test1 secondmemory limit per test256 megabytesinputstandard inputoutputstandard output

 distinct integers a, a, ..., an ai ≤ n). She replaces some of permutation elements with -1 value as a revenge.

k which has value equal to k ak = k). Your job is to proof to Iahub that trying to recover it is not a good idea. Output the number of permutations which could be originally Iahub's important permutation, modulo  ( + 7).

Input

 (n ≤ 2000). On the second line, there are n integers, representing Iahub's important permutation after Iahubina replaces some values with -1.

Output

Sample test(s)input

output
Note



-1 -1 4 3 -15
-1 -1 2 5 -1

開始看了傳說中的frog蛙神的部落格,表示看了一晚上都不解,若菜都是一把淚水啊!邊看邊問,終於理解了其中的要義,感謝frog1902的講解。題目地址:C. Iahub and Permutations

顯然所有已經填好的位置可以不管,我們只看 a[i] = -1 的位置。

x 表示目前有多少個位置使得a[i] = -1 且數字 i 已經被填在某個位置上,稱為無限制位置。

y 表示目前有多少個位置使得a[i] = -1 且數字 i 沒有被填在某個位置上,稱為有限制位置。


那麼,最一開始的時候,我們先把 y 個有限制位置拋棄不看。

因為a[i] = -1 且 i 也沒有出現在任何位置上,所以忽略不看不會有影響。


現在我們先把 x 個無限制的位置填好。

由於有 x 個數的 a[i] = -1 但是數字 i 已經被使用了。所以也一定有 x 個數的a[i] != -1但是數字 i 還沒被用。

就把這 x 個沒使用的數字放在 x 個被填的位置上。方法數是 x! 。


現在我們把 y 個無限制的位置一個接一個的加進來

用 d[i] 表示已經有多少個無限制的位置被加進來,且不違反錯排的規則。

顯然d[0] = x ! 。我們所要求的就是d[y].


如果此時我們把第 i 個有限制的位置加進來。分以下幾種情況:

1)我們從 x 個無限制的的位置中找一個 j ,令a[i] = a[j],a[j] = i。規約到d[i - 1]的方案數。

-1 -1 2 5 -1

2)我們從i - 1個有限制的位置中找一個位置 j ,令a[i] = j,a[j] = i。規約到d[i - 2]的方案數。

-1 -1 3 4 -1

3)我們從i - 1個有限制的位置中找一個位置 j ,令a[i] = j,但是a[j] != i。規約到d[i - 1]的方案數。也就相當於由原來的 d[j] != j 限制變為了d[j] != i,其它限制不變。

-1 -1 3 4 -1

AC代碼:

#include<iostream>#include<cstring>#include<cmath>#include<cstdio>using namespace std;int mod=1e9+7;__int64 d[2002];int a[2002];__int64 cal(int p){    __int64 ans=1;    int i;    for(i=2;i<=p;i++)        ans=(ans*i)%mod;    return ans;}int main(){    int n,x,y;    while(~scanf("%d",&n))    {        int cnt=0,t=0;  //cnt記錄可以填的個數,t記錄填的數字被佔用的個數        for(int i=1;i<=n;i++)        {            scanf("%d",&a[i]);            if(a[i]==-1)                cnt++;        }        for(int i=1;i<=n;i++)        {            if(a[i]>0)            {                if(a[a[i]]==-1)                    t++;            }        }        x=t;  //x是無限制的個數        y=cnt-t;        d[0]=cal(x);   //d[0]=x!        for(int i=1;i<=y;i++)        {            d[i]=((x+i-1)*d[i-1])%mod;            if(i>1)                d[i]=(d[i]+(i-1)*d[i-2])%mod;        }        printf("%I64d\n",d[y]);    }    return 0;}/*5-1 -1 4 3 -15-1 -1 4 -1 -15-1 -1 2 5 -1*/



相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.