题意
问长度为n的1~n的排列,且逆序对为k的方案数有多少
\(n,k\leq 1000\)
思路
假设前\(1\)~\(i\)已经排列好,此时逆序对为\(k\),那么我们来讨论插入\(i+1\)时候的状态
\(i+1\)根据插入位置的不同,可以产生\(0\)到\(i\)个逆序对
根据这个特点我们设\(dp[i][j]\)为前\(i\)个数,逆序对为\(j\)的排列的方案数
\(dp[i][j]=f[i-1][j-i+1]+f[i-1][j-i+2]+\cdots +f[i-1][j]\)
代码
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<string> //#include<stack> #include<queue> #include<deque> #include<set> #include<vector> #include<map> #define fst first #define sc second #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define lson l,mid,root<<1 #define rson mid+1,r,root<<1|1 #define lc root<<1 #define rc root<<1|1 #define lowbit(x) ((x)&(-x)) using namespace std; typedef double db; typedef long double ldb; typedef long long ll; typedef long long LL; typedef unsigned long long ull; typedef pair<int,int> PI; typedef pair<ll,ll> PLL; const db eps = 1e-6; const int mod = 10000; const int maxn = 5e5+100; const int maxm = 2e6+100; const int inf = 0x7f3f3f3f; //const db pi = acos(-1.0); const ull base = 201326611; int f[1111][1111]; int sum[1111]; int n,k; int main() { scanf("%d %d", &n, &k); f[1][0]=1; sum[0]=1; for(int j = 1; j <= 1000; j++){ sum[j]=sum[j-1]; sum[j]%=mod; } for(int i = 2; i <= n; i++){ f[i][0]=1; for(int j = 1; j <= 1000; j++){ int g = j-i; if(j-i<0)g=0; else g=sum[g]; f[i][j]=sum[j]-g+mod; f[i][j]%=mod; } sum[0]=1; for(int j = 1; j <= 1000; j++){ sum[j]=sum[j-1]+f[i][j]; sum[j]%=mod; } } printf("%d",f[n][k]); return 0; }