版权声明:虽然本蒟蒻很菜,但各位dalao转载请注明出处谢谢。 https://blog.csdn.net/xuxiayang/article/details/89155006
有 组询问,每次询问长度为 ,每个数的范围都在 , (最长上升子序列,在本题中严格单调)的长度为 的合法方案数,答案对 取模
这题是一道比较显然的 ,我是在考场时就想出方程,然后并且成功拿到了30,后来预处理一个前缀和就 了
设 表示长度为 的序列, 的末尾数组为 , 的长度为 时的方案数
边界: ,表示长度为1的序列填 这个数字 的长度都为1,方案也只有1种
如果这一位填了 , 长度不变,显然上一位是有 种选择的,即填 ,
如果这一位填了 ,导致 长度发生了变化,那么这时我们就要枚举一个 ,表示上一次选的数字,此时
回答时
这样子复杂度
我们发现, 是一段连续的数字,也就是我们加的 是可以用前缀和表示的,这样我们的时间复杂度就跌到了
#include<cstdio>
#include<cctype>
#include<cstring>
#define ri int
#define WYC 1000000007
using namespace std;int t,n,k,p;
long long f[110][313][110],ans,sum[101][101][301];
inline int read()
{
char c;int d=1,f=0;
while(!isdigit(c=getchar())) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48;
while(isdigit(c=getchar())) f=(f<<3)+(f<<1)+c-48;
return d*f;
}
signed main()
{
t=read();
for(ri i=1;i<=300;i++) f[1][i][1]=1,sum[1][1][i]=i;
for(ri i=2;i<=100;i++)
for(ri l=1;l<=i;l++)
for(ri j=l;j<=300;j++)
{
(f[i][j][l]+=f[i-1][j][l]*j)%=WYC;
(f[i][j][l]+=sum[i-1][l-1][j-1])%=WYC;
(sum[i][l][j]=sum[i][l][j-1]+f[i][j][l])%=WYC;
}
while(t--)
{
n=read();k=read();p=read();
ans=0;
for(ri i=p+1;i<=k;i++) (ans+=f[n][i][p+1])%=WYC;
printf("%lld\n",ans);
}
}