题意概括
题面很清楚,不多赘述了。
分析
设 \(f_{i,j}\) 表示已用前 \(i\) 个数,使数列出现 \(j\) 个逆序对的方案数。
因为从小到大枚举 \(i\),所以填 \(i\) 时前面所有的数都比它小,那么 \(i\) 每向前移动一位,就会增加一个逆序对。所以可以直接枚举每一个 \(i,j\),再枚举插入 \(i\) 的位置,转移方程是 \(f_{i,j}=\sum\limits_{k=0}^{i-1} f_{i-1,j-k}\)。但这样是 \(O(nc^2)\) 的,会 TLE。
但是可以发现,第三维就是在找 \([j-i+1,i-1]\) 的区间,所以可以加入一个前缀和,把复杂度优化到 \(O(nc)\),通过这道题。
Code
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll mod=1e9+7;
ll n,c,f[10005]={1},s[10005];
signed main(){
cin>>n>>c;
for(ll i=2;i<=n;++i){
s[0]=f[0];
for(ll j=1;j<=c;++j)s[j]=(s[j-1]+f[j])%mod;//预处理前缀和
for(ll j=0;j<=c;++j){
if(j>=i)f[j]=(s[j]-s[j-i]+mod)%mod;
else f[j]=s[j];
}//计算f[j]
}
cout<<f[c];
return 0;
}
标签:ll,nc,long,枚举,2006,2007,逆序,COCI,mod
From: https://www.cnblogs.com/run-away/p/18030327