给出n个数字,分别为1,2,3,……,n。从中选出t个数字,且这t个数字和为x的方案数为ft,x 。给出m。输出下面的值:
数据满足n <= 20000,m <= min(10, n)。
标签:
给出n个数字,分别为1,2,3,……,n。从中选出t个数字,且这t个数字和为x的方案数为ft,x 。给出m。输出下面的值:
数据满足n <= 20000,m <= min(10, n)。
第一行输入T表示测试数据的行数。接下来T行,每行两个数字n, m。T <= 20。
对于每组测试数据,输出一行。
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> using namespace std; #define maxn 21000 #define LL long long #define MOD 1000000007 int n,m; LL answer; LL d[15][maxn*15]; LL f[15]; void init() { memset(d,0,sizeof(d)); for(int i=1;i<15;i++) f[i]=1; } LL pow(int a,int b) { LL ans=1; for(int i=1;i<=b;i++) { ans=(ans*a)%MOD; } return ans; } void solve() { for(int i=1;i<=n;i++) d[1][i]=1; f[1]=pow(2,n); // cout<<f[1]<<endl; for(int t=2;t<=m;t++) { for(int x=1;x<(t*n);x++) { d[t][x]=(d[t][x-t]+d[t-1][x-t]-d[t-1][x-(n+1)] + MOD)%MOD; f[t]=(f[t]*(d[t][x]+1))%MOD; //printf("%d %d %d\n",t,x,d[t][x]); } //最小值要么为1,要么不为1, //当最小值为1时,最大值可能为n,需要减去d[t-1][x-(n+1)]; //当最小值不为1,最大值也可能为n,需要减去d[t-1][x-(n+1)]; //由于这两种情况互斥,所以最多只需要减1次 //cout<<endl; // while(f[t]<0) //cout<<f[t]<<endl; } answer=0; for(int t=1;t<=m;t++) { // printf("f %d %d\n",t,f[t]); answer=(answer+f[t])%MOD; answer=answer%MOD; } // while(answer<0) printf("%lld\n",answer%MOD); } int main() { // cout<<(-5)%3<<endl; int t; scanf("%d",&t); while(t--) { init(); scanf("%d%d",&n,&m); solve(); } return 0; }
标签:
原文地址:http://www.cnblogs.com/xianbin7/p/4678186.html