• ●BZOJ 4361 isn


    题链:

    http://www.lydsy.com/JudgeOnline/problem.php?id=4361

    题解:

    容斥,DP,树状数组
    注意题意:一旦变成了非降序列,就停止操作。即对非降序列进行操作是非法的。
    首先求出 dp[i][j]:表示以第i个数作为结尾且长度为j的不降序列的种类数
    转移显然 : dp[i][j]+=dp[k][j-1] k<i且a[k]<=a[j],复杂度 O(N^3)
    可以用 树状数组优化到 O(N^2*log2N),(要开 N个树状数组)
    然后得到 g[j]+=dp[i][j]:表示长度为 j的不降序列的种类数。
    在令 w[i]=g[i]*(N-i)!含义是留下的i个数,组成非降序列,那 N-i个数有(N-i)!种方法把它们拿走。
    那么 答案就是  w[1] + w[2] + w[3] +.....
    完了么?当然没有,细细一想,w[ ]好像有问题:
    不是说一旦变成了非降序列,就要停止操作么,
    所以 w[i]完全可能会存在某个方案还没操作完就已经非降了,那么要减去这些方案。
    怎么减呢?
    不难发现,w[i+1]里包含了两类方案,
    一类是取了N-(i+1)个数后恰好变成非降序列,这类是合法的操作
    另一类是还没有取到第N-(i+1)个数就已经非降了,那么这类操作就是非法的
    同时对于 w[i]来说,其中包含的非法方案就是上面两类操作的方案数*(i+1),                  
    即w[i+1]*(i+1)
    所以减去就好了 : w[i]-=w[i+1]*(i+1)
    最后的答案才是 w[1] + w[2] + w[3] +.....

    代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 2050
    #define _ %mod
    #define filein(x) freopen(#x".in","r",stdin);
    #define fileout(x) freopen(#x".out","w",stdout);
    using namespace std;
    const int mod=1000000007;
    struct BIT{
    	int val[MAXN][MAXN],N;
    	void Init(int n){
    		N=n; 
    		memset(val,0,sizeof(val));
    	}
    	int Lowbit(int x){
    		return x&-x;
    	}
    	void Modify(int id,int p,int x){
    		for(int i=p;i<=N;i+=Lowbit(i))
    			val[id][i]=(1ll*val[id][i]+x)_;
    	}
    	int Query(int id,int p){
    		int ans=0;
    		for(int i=p;i;i-=Lowbit(i))
    			ans=(1ll*ans+val[id][i])_;
    		return ans;
    	}
    }t;
    int dp[MAXN][MAXN],g[MAXN],a[MAXN],fac[MAXN]; //dp[i][j] 以i结尾,序列长度为 j的方案
    int N,ANS;
    int main()
    {
    	static int tmp[MAXN],M;
    	scanf("%d",&N); t.Init(N); fac[0]=1;
    	for(int i=1;i<=N;i++) fac[i]=(1ll*fac[i-1]*i)_;
    	for(int i=1;i<=N;i++) scanf("%d",&a[i]),tmp[i]=a[i];
    	sort(tmp+1,tmp+N+1); M=unique(tmp+1,tmp+N+1)-tmp-1;
    	for(int i=1;i<=N;i++) a[i]=lower_bound(tmp+1,tmp+M+1,a[i])-tmp;
    	for(int i=1;i<=N;i++){
    		for(int j=i;j>=2;j--){ 
    			dp[i][j]=t.Query(j-1,a[i]);
    			t.Modify(j,a[i],dp[i][j]);
    		}
    		dp[i][1]=1; t.Modify(1,a[i],dp[i][1]);
    	}
    	for(int j=1;j<=N;j++){ 
    		for(int i=1;i<=N;i++)
    			g[j]=(1ll*g[j]+dp[i][j])_;
    		g[j]=(1ll*g[j]*fac[N-j])_;
    	} 
    	for(int i=1;i<=N;i++)
    		g[i]=(1ll*g[i]-(1ll*g[i+1]*(i+1))_+mod)_,ANS=(1ll*ANS+g[i])_;
    	printf("%d",ANS);
    	return 0;
    }
    

  • 相关阅读:
    CSS简介
    jQuery学习笔记一
    JavaScript基础testDemo
    JavaScript知识点记录
    js实现404页面倒计时跳转 猫
    html5动画之等待加载动画 猫
    开发jquery插件小结 猫
    jquery做一个小的轮播插件有BUG,后续修改 猫
    js倒计时跳转jquery插件版 猫
    nodejs安装配置 猫
  • 原文地址:https://www.cnblogs.com/zj75211/p/8029380.html
Copyright © 2020-2023  润新知