XDU-1112 Too Stupid(DP)

1112: Too Stupid

Time Limit: 1 Sec   Memory Limit: 128 MB
[ Submit][ Status][ Web Board]

Description

某天 light由于太富而且太帅遭到了歹徒的袭击,现在他遇到了n个歹徒,准备对light施行不法行为,虽然light身体强壮,但是毕竟只有一个人肯定打不过那么多歹徒,但是高智商的light觉得歹徒们非常stupid,不打算束手就擒。经过观察他发现这些歹徒是有派系之分的
我们规定 A与B,B与C为同一个派系,那么A与C也为同一个派系
light认为,如果了解了歹徒的派系情况,他就可以用一些特殊的计谋战胜他们。但是,歹徒之间形成派系的可能性很多,而light对此一无所知。
现在问题来了,歹徒们有多少种可能形成派系的方案呢。由于方案数可能会很大,请对1000000007取模后输出。

Input

多组数据,处理到EOF

每组数据 第一行整数n       1 <= n <=1000

Output

输出方案数, 并对1000000007(1e9+7)取模

Sample Input

1
2
3

Sample Output

1
2
5

HINT

 三个歹徒的情况:


1:A与B同派系,C不同


2:B与C同派系,A不同


3:A与C同派系,B不同


4:A,B,C三人同派系


5:A,B,C三人都不同派系


放在专题中就只想DP,还是想了好久(要是比赛估计就想不出了...),从一维状态想到二维状态

思维过程:

刚开始只想到一维

i个人比i-1个人多出来的一个人可以:①自己一个派系②在i-1个人出现的派系中

①的情况很好转移,但是②不好办,因为不同方案的派系数不同,转移出的方案也不同

所以将状态用二维表示,dp[i][j]表示i个人j个不同的派系有多少方案

即 ①:dp[i-1][j-1]

     ②:dp[i-1][j]*j(由于有j个不同的派系,所以第i个人可以出现在j个派系中,则方案数要乘以j)

此时则有dp[i][j]=(dp[i-1][j-1]+dp[i-1][j]*j);


#include <cstdio>
using namespace std;

const long long MOD=1000000007;
long long dp[1001][1002];//dp[i][j]表示i个人j个不同的派系有多少方案
int main() {
    int i,j,n;
    dp[1][0]=0,dp[1][1001]=dp[1][1]=1;
    for(i=2;i<1001;++i) {
        dp[i][0]=0,dp[i][1001]=dp[i][i]=1;
        for(j=1;j<i;++j) {
            dp[i][j]=(dp[i-1][j-1]+dp[i-1][j]*j)%MOD;//由于此处有乘法,所以只得换成long long了
            if((dp[i][1001]+=dp[i][j])>=MOD)
                dp[i][1001]-=MOD;
        }
    }
    while(1==scanf("%d",&n))
        printf("%lld\n",dp[n][1001]);//XDU交题long long得用lld否则会Output Limit Exceed,第一次被坑了好久才发现...
    return 0;
}


你可能感兴趣的:(dp,xdu)