正题
题目大意
求有多少个长度为nnn且由1∼p1\sim p1∼p组成的序列满足在求最大值时交换了kkk次。
解题思路
考虑dpdpdp预处理。
用fi,j,kf_{i,j,k}fi,j,k表示长度为iii,最大的数是jjj,交换了kkk次
显然有fi,j,k=fi−1,p,k−1+fi−1,j,k∗j(p<j)f_{i,j,k}=f_{i-1,p,k-1}+f_{i-1,j,k}*j(p<j)fi,j,k=fi−1,p,k−1+fi−1,j,k∗j(p<j)
对于fi−1,p,k−1f_{i-1,p,k-1}fi−1,p,k−1我们可以前缀和优化到O(npk)O(npk)O(npk)
然后我们要考虑最大的不一定是ppp,所以ans=∑i=1pfn,i,kans=\sum _{i=1}^p f_{n,i,k}ans=i=1∑pfn,i,k
时间复杂度O(NPK+∑p)O(NPK+\sum p)O(NPK+∑p)
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll XJQ=1e9+7;
ll t,f[110][310][110],n,k,p,ans,sum[310][110];
int main()
{scanf("%lld",&t);for(ll i=1;i<=300;i++)f[1][i][1]=1;for(ll j=1;j<=300;j++)sum[j][1]=(sum[j-1][1]+f[1][j][1])%XJQ; for(ll i=2;i<=100;i++){for(ll j=1;j<=300;j++)for(ll k=1;k<=min(i,j);k++)f[i][j][k]=(f[i-1][j][k]*j%XJQ+sum[j-1][k-1])%XJQ;memset(sum,0,sizeof(sum));for(ll j=1;j<=300;j++)for(ll k=1;k<=i;k++)sum[j][k]=(sum[j-1][k]+f[i][j][k]%XJQ);}while(t--){scanf("%lld%lld%lld",&n,&k,&p);p++;ans=0;for(ll i=1;i<=k;i++)ans=(ans+f[n][i][p])%XJQ;printf("%lld\n",ans);}
}