转化为求选择k个数,和为(n+1)*k的方案数
保证,每个数[1,2*n+1]且最多选择一次。
限制k个很小,所以用整数划分的第二种方法
f[i][j],用了i个,和为j
整体+1,或者取一个1再整体加1(为了保证只选择一次)
j>=2*n+2时,整体+1,所以必然存在一个选择了2*n+2的方案,减掉f[i-1][j-(2*n+2)]即可
#include<bits/stdc++.h> #define reg register int #define il inline #define fi first #define se second #define mk(a,b) make_pair(a,b) #define numb (ch^'0') using namespace std; typedef long long ll; template<class T>il void rd(T &x){ char ch;x=0;bool fl=false; while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true); for(x=numb;isdigit(ch=getchar());x=x*10+numb); (fl==true)&&(x=-x); } template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');} template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');} template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('\n');} namespace Miracle{ int f[11][(10000+1)*10+5]; int n,k,p; int main(){ int t; rd(t); while(t--){ rd(n);rd(k);rd(p); memset(f,0,sizeof f); f[0][0]=1; for(reg j=1;j<=(n+1)*k;++j){ for(reg i=1;i<=min(k,j);++i){ f[i][j]=(f[i][j-i]+f[i-1][j-i]-(j>=(n+1)*2?f[i-1][j-(n+1)*2]:0)+p)%p; } } printf("%d\n",f[k][(n+1)*k]); } return 0; } } signed main(){ Miracle::main(); return 0; } /* Author: *Miracle* Date: 2019/3/20 16:26:21 */