程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> bzoj4361 isn

bzoj4361 isn

編輯:C++入門知識

bzoj4361 isn


Description

給出一個長度為n的序列A(A1,A2...AN)。如果序列A不是非降的,你必須從中刪去一個數, 這一操作,直到A非降為止。求有多少種不同的操作方案,答案模10^9+7。

Input

第一行一個整數n。 接下來一行n個整數,描述A。

Output

一行一個整數,描述答案。

Sample Input

4
1 7 5 3

Sample Output

18

HINT

1<=N<=2000

Source

用f[i][j]表示以a[i]結尾,長度為j的非降子序列個數,這可以用樹狀數組優化的DP解決,時間復雜度O(n^2logn)。

再用g[i]表示長度為i的非降子序列個數,很顯然g[i]=∑f[k][i],時間復雜度O(n^2)。

然後根據容斥原理,ans=∑((n-i)!*g[i]-(n-i-1)!*g[i+1]*(i+1))。

#include
#include
#include
#include
#include
#include
#include
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 2005
#define mod 1000000007
using namespace std;
int n,cnt;
int a[maxn],b[maxn],bb[maxn];
ll f[maxn][maxn],g[maxn],fac[maxn],s[maxn][maxn];
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline void add(int id,int pos,ll x)
{
	for(;pos<=n;pos+=(pos&(-pos))) (s[id][pos]+=x)%=mod;
}
inline ll query(int id,int pos)
{
	ll ans=0;
	for(;pos;pos-=(pos&(-pos))) (ans+=s[id][pos])%=mod;
	return ans;
}
int main()
{
	n=read();
	F(i,1,n) a[i]=b[i]=read();
	sort(b+1,b+n+1);
	F(i,1,n) if (i==1||b[i]!=b[i-1]) bb[++cnt]=b[i];
	F(i,1,n) a[i]=lower_bound(bb+1,bb+cnt+1,a[i])-bb;
	fac[0]=1;
	F(i,1,n) fac[i]=fac[i-1]*i%mod;
	add(0,1,1);
	F(i,1,n) D(j,i,1)
	{
		f[i][j]=query(j-1,a[i])%mod;
		add(j,a[i],f[i][j]);
	}
	F(i,1,n) F(j,i,n) (g[i]+=f[j][i])%=mod;
	ll ans=0;
	F(i,1,n) ans=(((ans+g[i]*fac[n-i])%mod-g[i+1]*fac[n-i-1]%mod*(i+1)%mod)%mod+mod)%mod;
	printf("%d\n",ans);
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved