zoukankan      html  css  js  c++  java
  • 洛谷P3643 [APIO2016]划艇(组合数学)

    题面

    传送门

    题解

    首先区间个数很少,我们考虑把所有区间离散化(这里要把所有的右端点变为(B_i+1)代表的开区间)

    (f_{i,j})表示考虑到第(i)个学校且第(i)个学校必选,这个学校选择的数在离散后的第(j)个区间内,方案数是多少

    怎么转移呢,我们考虑枚举上一个不在第(j)个区间的学校(k),设([k+1,i])中有(a)个学校是可以选在第(j)个区间的,且第(j)个区间的长度为(b),然后暴力枚举这(m)个数中有(q)个选了,那么转移就是

    [f_{i,j}=sum_{k=0}^{i-1}left(sum_{p=0}^{j-1}f_{k,p} ight)sum_{q=1}^{min(a,b)}{a-1choose q-1}{bchoose q} ]

    (sum_{p=0}^{j-1}f_{k,p})显然是可以做一个前缀和的

    然后对于(sum_{q=1}^{min(a,b)}{a-1choose q-1}{bchoose q}),它等于(sum_{q=1}^{min(a,b)}{a-1choose a-q}{bchoose q}),可以理解为有(a+b-1)个数,要选出(a)个,然后枚举前(a-1)个数里选了多少个和后(b)个里选了多少个,那么上面的柿子就等价于({a+b-1choose a})

    于是递推式就可以化为

    [f_{i,j}=sum_{k=0}^{i-1}{a+b-1choose a}left(sum_{p=0}^{j-1}f_{k,p} ight) ]

    然后没有然后了

    //minamoto
    #include<bits/stdc++.h>
    #define R register
    #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    using namespace std;
    char buf[1<<21],*p1=buf,*p2=buf;
    inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
    int read(){
        R int res,f=1;R char ch;
        while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
        for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
        return res*f;
    }
    const int N=1005,P=1e9+7;
    inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
    inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
    inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
    int ksm(R int x,R int y){
    	R int res=1;
    	for(;y;y>>=1,x=mul(x,x))if(y&1)res=mul(res,x);
    	return res;
    }
    int A[N],B[N],D[N],inv[N],len[N],C[N],f[N][N],g[N][N];
    int n,m,res;
    int main(){
    //	freopen("testdata.in","r",stdin);
    	n=read();
    	fp(i,1,n)A[i]=read(),B[i]=read(),D[++m]=A[i],D[++m]=B[i]+1;
    	D[++m]=0,sort(D+1,D+1+m),D[m+1]=D[m]+1,m=unique(D+1,D+m+2)-D-1;
    	fp(i,1,m-1)len[i]=D[i+1]-D[i];
    	fp(i,1,n){
    		A[i]=lower_bound(D+1,D+1+m,A[i])-D,
    		B[i]=upper_bound(D+1,D+1+m,B[i])-D-1;
    	}
    	--m;
    	inv[0]=inv[1]=1;fp(i,2,n)inv[i]=mul(P-P/i,inv[P%i]);
    	f[0][0]=1;
    	fp(i,0,m)g[0][i]=1;
    	fp(i,1,n){
    		for(R int j=A[i],a,b;j<=B[i];++j){
    			a=len[j]-1,b=0,C[i]=1;
    			fd(k,i-1,0)
    				A[k+1]<=j&&B[k+1]>=j?(C[k]=1ll*(++a)*inv[++b]%P*C[k+1]%P):C[k]=C[k+1];
    			fd(k,i-1,0)f[i][j]=add(f[i][j],mul(C[k],g[k][j-1]));
    		}
    		g[i][0]=f[i][0];
    		fp(j,1,m)g[i][j]=add(f[i][j],g[i][j-1]);
    		res=add(res,g[i][m]);
    	}
    	printf("%d
    ",res);
    	return 0;
    }
    
  • 相关阅读:
    使用python3安装frida-tools出错
    xposed代码示例
    android studio3.4打jar包
    uiautomator代码例子--java
    Mac下不能成功打开uiautomatorviewer的问题解决
    mac下生成keystore
    Python杨辉三角算法
    Python迭代器:捕获Generator的返回值
    Python函数:一个简单的迭代
    Python参数组合
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/10560572.html
Copyright © 2011-2022 走看看