「BZOJ 4361」isn 题解
「BZOJ 4361」isn 题解
知识点
DP,组合数学,容斥,树状数组。
分析
首先,我们不考虑「非降时停止」这个限制,那么则可用 DP 求解。
设 \(f_{i,j}\) 表示 \(1\sim i\) 中,组成一个长度为 \(j\) 的非降子序列的方案数。初态和转移式:
\[\forall i,f_{i,1} = 1\\
f_{i,j} = \sum_{k<i} f_{k,j-1}[a_{k} \le a_i] \\
\]
这个问题答案就是:
\[\sum_{j=1}^n j\cdot (n-j)!\sum_{i=j}^{n} f_{i,j}
\]
然后我们来考虑「非降时停止」:其实只要把每个不合法的从原本的减掉即可,而这些不合法的我们都可以从已有的 DP 状态中推出来。
我们简化一下,设 \(g_i\) 表示所有组成长度为 \(i\) 的非降子序列的方案数,即:
\[g_i = \sum_{j=i}^n f_{j,i} \\
\]
那么考虑「非降时停止」的组成长度为 \(i\) 的非降子序列方案数就是:\((n-i)!\cdot g_i - (i+1)(n-i-1)!\cdot g_{i+1}\)。所以累加即可。
DP 暴力可做到 \(O(n^3)\),离散化后用树状数组即可优化到 \(O(n^2\log_2{n})\)。
代码
//#define Plus_Cat ""
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ll long long
#define RCL(a,b,c,d) memset(a,b,sizeof(c)*(d))
#define FOR(i,a,b) for(int i(a);i<=(int)(b);++i)
#define DOR(i,a,b) for(int i(a);i>=(int)(b);--i)
#define tomax(a,...) ((a)=max({(a),__VA_ARGS__}))
#define tomin(a,...) ((a)=min({(a),__VA_ARGS__}))
#define EDGE(g,i,x,y) for(int i=(g).h[(x)],y=(g)[(i)].v;~i;y=(g)[(i=(g)[i].nxt)>0?i:0].v)
#define main Main();signed main(){ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);return Main();}signed Main
using namespace std;
constexpr int N(2e3+10);
namespace Modular {
#define Mod 1000000007
int fac[N];
//Modular
void Init(const int n=N-5) {
FOR(i,fac[0]=1,n)fac[i]=mul(fac[i-1],i);
}
} using namespace Modular;
int n,ans;
int a[N],b[N],f[N];
class BIT {
private:
int c[N];
public:
void Init() { RCL(c+1,0,int,b[0]); }
#define lowbit(i) ((i)&-(i))
void Plus(int x,int d) { if(x>0)for(; x<=b[0]; x+=lowbit(x))toadd(c[x],d); }
#undef lowbit
int Sum(int x) {
int ans(0);
if(x>0)for(; x; x&=x-1)toadd(ans,c[x]);
return ans;
}
} bit;
signed main() {
#ifdef Plus_Cat
freopen(Plus_Cat ".in","r",stdin),freopen(Plus_Cat ".out","w",stdout);
#endif
cin>>n,Init(n),ans=mul(n,fac[n-1]);
FOR(i,1,n)cin>>a[i],b[i]=a[i],f[i]=1;
sort(b+1,b+n+1),b[0]=unique(b+1,b+n+1)-b-1;
FOR(i,1,n)a[i]=lower_bound(b+1,b+b[0]+1,a[i])-b;
FOR(len,2,n) {
bit.Init(),bit.Plus(a[len-1],f[len-1]),f[len-1]=0;
int sum(0);
FOR(i,len,n) {
int tmp(bit.Sum(a[i]));
bit.Plus(a[i],f[i]),toadd(sum,f[i]=tmp);
}
toadd(ans,Mod-mul(sum,len-1,fac[n-len]));
}
cout<<ans<<endl;
return 0;
}

浙公网安备 33010602011771号