BZOJ4361: isn
作者:互联网
BZOJ4361: isn
https://www.lydsy.com/JudgeOnline/problem.php?id=4361
Sol.
最终的状态一定是一个不降子序列。
令f[i][j]表示长度为i,最后一个数为a[j]不降子序列个数。
那么有f[i][j]=f[i-1][k](k<=j&&a[k]<=a[j]) 树状数组优化转移。
考虑g[i]= $ \sum $ f[i][1..n]
$ g[i] \times (n-i)! $ 就是i的答案。
然而这样会重,有可能还没删完就不降了
方案数要减去g[i+1]*(i+1) 相当于g[i+1]乘上枚举最后删的点:i+1种
#include<cstdio> #include<iostream> #include<cstdlib> #include<cstring> #include<algorithm> #include<cmath> #include<map> #define maxn 2005 #define mod 1000000007 #define ll long long using namespace std; int n,a[maxn],A[maxn],cnt; ll h[maxn],f[maxn][maxn],g[maxn],tr[maxn]; map<int,int>ls; ll ask(int x){ ll sum=0;for(int i=x;i;i-=i&-i)(sum+=tr[i])%=mod;return sum; } void add(int x,ll v){ for(int i=x;i<=cnt;i+=i&-i)(tr[i]+=v)%=mod; } void lsh(){ sort(A+1,A+n+1); for(int i=1;i<=n;i++)if(!ls[A[i]])ls[A[i]]=++cnt; } int main(){ cin>>n; for(int i=1;i<=n;i++)scanf("%d",&a[i]),A[i]=a[i]; lsh(); for(int i=1;i<=n;i++)a[i]=ls[a[i]]; h[0]=1;for(int i=1;i<=n;i++)h[i]=1LL*h[i-1]*i%mod; for(int i=1;i<=n;i++)f[1][i]=1; for(int j=2;j<=n;j++){ for(int i=1;i<=n;i++){ (f[j][i]+=ask(a[i]))%=mod; add(a[i],f[j-1][i]); } for(int i=1;i<=cnt;i++)tr[i]=0; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)g[i]=(g[i]+f[i][j])%mod; ll ans=0; for(int i=1;i<=n;i++)g[i]=g[i]*h[n-i]%mod; for(int i=1;i<=n;i++)ans=(ans+g[i]-g[i+1]*(i+1))%mod; ans=(ans%mod+mod)%mod; cout<<ans<<endl; return 0; }
标签:int,ll,define,maxn,isn,include,sum,BZOJ4361 来源: https://www.cnblogs.com/liankewei/p/11811178.html