dp+内存压缩+前缀和+离线处理
dp[i][j] 表示 n=i,k=j 时的答案。
pre[i][j] 表示 dp[i][j] 的前缀和。
转移方程:
dp[i][j]=pre[i-1][j]-(j-i>=0?pre[i-1][j-i]:0)
#include<bits/stdc++.h>
using namespace std;
const long long mod=1e9+7;
long long dp[2][20020],pre[2][20020],ans[10010];
int n[10010],k[10010];
int main()
{
int T,i,j,t;
scanf("%d",&T);
for(i=0;i<T;i++)
{
scanf("%d%d",&n[i],&k[i]);
}
memset(dp,0,sizeof(dp));
memset(pre,0,sizeof(pre));
dp[1][0]=1;
for(j=0;j<=20000;j++)
pre[1][j]=1;
for(i=2;i<=1000;i++)
{
dp[i&1][0]=pre[i&1][0]=1;
for(j=1;j<=20000;j++)
{
if(j<=i*(i-1)/2)
dp[i&1][j]=(pre[i&1^1][j]-(j-i>=0?pre[i&1^1][j-i]:0)+mod)%mod;
pre[i&1][j]=(pre[i&1][j-1]+dp[i&1][j])%mod;
}
for(j=0;j<T;j++)
{
if(n[j]==i)
ans[j]=dp[i&1][k[j]];
}
}
for(i=0;i<T;i++)
printf("%lld\n",ans[i]);
}