20140708 testB DP 组合数学

因为 long long 运算过程中的问题WA了好久 >_<

以后有 long long 的时候应该注意 int 与long long 之间转换的时候的问题。。

题目大意就是把[ai,bi] 作为区间,落在[1,N]上,互不重叠,长度互不相等。

然后dp[i][j] 表示 用j个不同的数组成i的方案数

       n-k

答案便是 k! * ∑ (C[n-i][k]*dp[i][k])

        i=0

 

 1 #include <cstdio>
 2 #include <cstring>
 3 using namespace std;
 4 #define N 1005
 5 #define MOD 1000000007
 6 typedef long long LL;
 7 
 8 int dp[N][N];
 9 int c[N][N];
10 LL kk[55];
11 
12 int min(int a,int b) {
13     return a<b?a:b;
14 }
15 
16 void _make() {
17     kk[0]=1;
18     for (int i=1;i<=50;i++) kk[i]=(kk[i-1]*i)%MOD;
19     
20     memset(dp,0,sizeof(dp));
21     dp[0][0]=dp[0][1]=1;
22     for (int k=1;k<N-1;k++) {
23         for (int i=N-1;i>=k;i--) {
24             for (int j=min(50,k+1);j>0;j--) {
25                 dp[i][j]=(dp[i][j]+dp[i-k][j-1])%MOD;
26             }
27         }
28     }
29             
30     memset(c,0,sizeof(c));
31     for (int i=1;i<N;i++) {
32         c[i][i]=c[i][0]=1;
33         for (int j=1;j<i;j++) {
34             c[i][j]=(c[i-1][j]+c[i-1][j-1])%MOD;
35         }
36     }    
37 }
38 
39 int main() {
40     _make();
41     int t;
42     int n,k;
43     scanf("%d",&t);
44     while (t--) {
45         scanf("%d%d",&n,&k);
46         if (k*(k+1)/2>n) {
47             printf("0\n");
48             continue;
49         }
50         LL ans=0;
51           
52         for (int i=0;i<=n-k;i++) {
53             LL s=(LL)c[n-i][k]*(LL)dp[i][k]%MOD;
54             ans=(ans+s)%MOD;
55         }
56         printf("%lld\n",(ans*kk[k])%MOD);
57     }
58 }
View Code

 

posted @ 2014-07-09 13:35  __fjm  阅读(126)  评论(0编辑  收藏  举报