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 }