题目大意:求逆序对数为k的n的排列有多少个
题解:
f[i][j]
表示前i个数逆序对为j的方案数
考虑转移:前i个数已经得到了确定的序列,现在插入i,可以新增
0到i−1
个逆序对,插到最后面,贡献为
f[i][j]
,插到i-2个数的后面贡献是
f[i−1][j−1]……
转移式:
f[i][j]=∑f[i−1][j−k](0≤k<i)
,但这样是
O(n3)
的,前缀和优化一下就是
O(n2)
了
我的收获:这种考虑方式挺常见的……
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define Mo 10000
const int M=1005;
int n,k,f[M][M],s[M][M];
void updata(int &x,int y){x-=y;x+=Mo;x%=Mo;}
void work()
{
f[0][0]=1;
for(int i=0;i<=k;i++) s[0][i]=1;
for(int i=1;i<=n;i++)
{
for(int j=0;j<=k;j++)
{
f[i][j]=s[i-1][j];
if(j>=i) updata(f[i][j],s[i-1][j-i]);
s[i][j]=(j?s[i][j-1]:0)+f[i][j];
s[i][j]%=Mo;
}
}
printf("%d\n",f[n][k]);
}
void init(){
cin>>n>>k;
}
int main()
{
init();
work();
return 0;
}