zoukankan      html  css  js  c++  java
  • bzoj4221 另类做法

    考场上连正解的第一步都没有想到,所以推出来了这个怪异的算法。

    我看着这个题面,就想着把每个袋鼠表示成一个区间[bi,ai],这样当某些区间两两没有交集,就可以合并成一个大的区间。而最后没有区间能合并了,说明剩下的区间有交集。考虑枚举这个交集[l,r]。

    此时我们的做法看着还是很离谱,但是仔细考虑一下,可以从这个交集入手。每一个大区间,他的头和尾必须跨过这个交集。继续想一想,可以把每个大区间分成三部分,第一次跨过l以及此前的,第一次跨过r以及此后的,还有l,r都没有跨过也就是在中间的。前两个部分显然预处理,在中间的部分最后算一下。

    先想前两个部分,可以分为两类,一类是跨过l的小区间(读入的区间),显然个数是固定的。另一类是(ri<l)的区间,这样的区间都是等价的。所以设(dp_{i,j})表示跨过i,有j个等价区间的方案数。每次从i-1转移到i,发现有一些区间从跨越变成等价区间,另一些区间加入了跨越区间,一些等价区间可以并到跨越区间,正好可以组合数算方案。

    然后是第三个部分。我在这卡了挺久,其实也不是很难。这个问题和原问题的区别就是,路径条数可以确定,而且不用考虑交集的问题。现在左右有两排个数相等的点,都是上面说的跨越和等价区间,中间是被[l,r]包含的小区间。另外有一些区间完全覆盖了[l,r],可以直接删除。考虑所有区间按l排序,按拓扑序依次加入区间。对于每个区间,他的前面有一些和他相交的区间,这些区间显然不在相同的链里,这些链不能放,而另外的链随意放。连dp都不用,直接做乘法就可以了。

    我们求出的是交集包含[l,r]的方案,最后做个简单容斥即可。

    如果您愿意实现我这个方法,我将不胜荣幸,并预祝您体验到调试代码的快乐。

    UPD:其实是(O(n^3))的,容斥只需要长度为1的减去长度为2的就行了。要好写多了。(其实直接从代码就能看出来独立性)

    #include<bits/stdc++.h>
    using namespace std;
    #define forg(i,x) for(register int i=fir[x];i;i=nxt[i])
    #define uu unsigned
    #define scanf a14=scanf
    #define rint register int
    #define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
    typedef long long ll;
    typedef uu long long ull;
    typedef pair<int,int>pii;
    int a14;
    inline int rd(int l,int r){return rand()%(r-l+1)+l;}
    
    const int mxn=603,mod=1e9+7;
    int n,ls[mxn],m;int lsx(int x){return lower_bound(ls+1,ls+m+1,x)-ls;}
    struct two{int l,r;two(){}two(int ll,int rr){l=ll,r=rr;}}a[mxn];
    ll f1[mxn][mxn],f2[mxn][mxn],C[mxn][mxn],jc[mxn];
    int cl[mxn],cr[mxn];
    int main(){
        scanf("%d",&n);for(int i=1,l,r;i<=n;++i)scanf("%d%d",&r,&l),ls[++m]=l,ls[++m]=r,a[i]=two(l,r);
        C[0][0]=1;for(int i=1;i<=n;++i){C[i][0]=1;for(int j=1;j<=i;++j)C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;}jc[0]=1;for(int i=1;i<=n;++i)jc[i]=jc[i-1]*i%mod;
        sort(ls+1,ls+m+1),m=unique(ls+1,ls+m+1)-ls-1;for(int i=1;i<=n;++i)a[i].l=lsx(a[i].l),a[i].r=lsx(a[i].r);
        for(int i=1;i<=n;++i)++cl[a[i].l],++cr[a[i].r];
        f1[0][0]=1;for(int i=1;i<=m;++i){
            int x=cr[i-1],y=cl[i];
            for(int j=0;j<=n;++j)if(f1[i-1][j]){
                int t=j+x;for(int k=0;k<=t;++k)(f1[i][t-k]+=f1[i-1][j]*C[t][k]%mod*C[y][k]%mod*jc[k])%=mod;
            }
        }
        f2[m+1][0]=1;for(int i=m;i;--i){
            int x=cl[i+1],y=cr[i];
            for(int j=0;j<=n;++j)if(f2[i+1][j]){
                int t=j+x;for(int k=0;k<=t;++k)(f2[i][t-k]+=f2[i+1][j]*C[t][k]%mod*C[y][k]%mod*jc[k])%=mod;
            }
        }
        ll ans=0;
        for(int i=1;i<=m;++i){
            ll B=1,re=0;
            for(int k=0;k<=n;++k,B=B*k%mod)if(f1[i][k]&&f2[i][k]){
                re+=B*f1[i][k]%mod*f2[i][k]%mod;
            }
            ans+=re%mod;
        }
        for(int l=1;l<m;++l){
            int r=l+1,x=cr[l],y=cl[r],k0=max(x,y);ll B=1;
            int rr=y-1;if(x>y)rr+=x-y;
            for(int i=0;i<=rr;++i)B=B*(k0-i)%mod;
            ll re=0;
            for(int k=k0;k<=n;++k,B=B*k%mod)if(f1[l][k-x]&&f2[r][k-y]){
                re+=B*f1[l][k-x]%mod*f2[r][k-y]%mod;
            }
            ans-=re%mod;
        }
        ans=(ans%mod+mod)%mod;printf("%lld
    ",ans);
        return 0;
    }
    
    #include<bits/stdc++.h>
    using namespace std;
    #define forg(i,x) for(register int i=fir[x];i;i=nxt[i])
    #define uu unsigned
    #define scanf a14=scanf
    #define rint register int
    #define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
    typedef long long ll;
    typedef uu long long ull;
    typedef pair<int,int>pii;
    int a14;
    inline int rd(int l,int r){return rand()%(r-l+1)+l;}
    
    const int mxn=603,mod=1e9+7;
    int n,ls[mxn],m;int lsx(int x){return lower_bound(ls+1,ls+m+1,x)-ls;}
    struct two{int l,r;two(){}two(int ll,int rr){l=ll,r=rr;}}a[mxn];
    ll f1[mxn][mxn],f2[mxn][mxn],C[mxn][mxn],jc[mxn];
    int cl[mxn],cr[mxn],cg[mxn];vector<int>vl[mxn],vr[mxn],vx[mxn];
    int cc[mxn],nn;ll re[mxn][mxn];
    struct zsz{int a[mxn];void clr(){memset(a,0,sizeof(a));}void add(int x){for(;x;x-=x&-x)++a[x];}int ask(int x){int r=0;for(;x<=m;x+=x&-x)r+=a[x];return r;}}ar;
    int main(){
        scanf("%d",&n);for(int i=1,l,r;i<=n;++i)scanf("%d%d",&r,&l),ls[++m]=l,ls[++m]=r,a[i]=two(l,r);
        C[0][0]=1;for(int i=1;i<=n;++i){C[i][0]=1;for(int j=1;j<=i;++j)C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;}jc[0]=1;for(int i=1;i<=n;++i)jc[i]=jc[i-1]*i%mod;
        sort(ls+1,ls+m+1),m=unique(ls+1,ls+m+1)-ls-1;for(int i=1;i<=n;++i)a[i].l=lsx(a[i].l),a[i].r=lsx(a[i].r);
        for(int i=1;i<=n;++i)++cl[a[i].l],++cr[a[i].r],vx[a[i].l].push_back(a[i].r);
        for(int i=1;i<=n;++i)for(int j=a[i].l;j<=a[i].r;++j)++cg[j],vl[j].push_back(a[i].r),vr[j].push_back(a[i].l);
        for(int i=1;i<=m;++i)sort(vl[i].begin(),vl[i].end()),sort(vr[i].begin(),vr[i].end()),sort(vx[i].begin(),vx[i].end());
        f1[0][0]=1;for(int i=1;i<=m;++i){
            int x=cr[i-1],y=cl[i];
            for(int j=0;j<=n;++j)if(f1[i-1][j]){
                int t=j+x;for(int k=0;k<=t;++k)(f1[i][t-k]+=f1[i-1][j]*C[t][k]%mod*C[y][k]%mod*jc[k])%=mod;
            }
        }
        f2[m+1][0]=1;for(int i=m;i;--i){
            int x=cl[i+1],y=cr[i];
            for(int j=0;j<=n;++j)if(f2[i+1][j]){
                int t=j+x;for(int k=0;k<=t;++k)(f2[i][t-k]+=f2[i+1][j]*C[t][k]%mod*C[y][k]%mod*jc[k])%=mod;
            }
        }
        for(int l=1;l<=m;++l)for(int r=l;r<=m;++r){
            int x=cg[l],y=cg[r];
            ar.clr();nn=0;int k2=0;for(int i:vl[l]){if(i>=r)break;ar.add(i);}
            int p=0,zs=vr[r].size();while(p!=zs&&vr[r][p]<=l)++p,--x,--y;
            for(int i=l+1;i<r;++i){
                for(int j:vx[i]){if(j>=r)break;cc[++nn]=ar.ask(i)+k2,ar.add(j);}
                for(;p!=zs&&vr[r][p]==i;++p)cc[++nn]=ar.ask(i)+(k2++);
            }
            for(;p!=zs;++p)assert(vr[r][p]==r),cc[++nn]=ar.ask(r)+(k2++);
            ll B=1;int k0=max(x,y);k2=k0-k2;
            if(x>y)for(int i=0;i<x-y;++i)B=B*(k2-i)%mod;
            for(int k=k0;k<=n;++k,B=B*(++k2)%mod)if(f1[l][k-x]&&f2[r][k-y]){
                ll fx=1;for(int i=1;i<=nn;++i)fx=fx*(k-cc[i])%mod;
                fx=fx*B%mod;
                re[l][r]+=fx*f1[l][k-x]%mod*f2[r][k-y]%mod;
            }
            re[l][r]%=mod;
        }
        ll ans=0;for(int l=1;l<=m;++l)for(int r=l;r<=m;++r)ans+=re[l][r]-re[l-1][r]-re[l][r+1]+re[l-1][r+1];
        ans=(ans%mod+mod)%mod;printf("%lld
    ",ans);
        return 0;
    }
    
    
  • 相关阅读:
    zabbix--完整安装攻略
    python--8大排序(原理+代码)
    python--二分法查找
    celery生产者-消费者
    python--基础知识点梳理(之数据结构)
    mysql--事务详解
    python--基础知识点梳理(三)深浅拷贝、进线协程、os和sys、垃圾回收机制、读文件的三种方式
    python--基础知识点梳理(二)面向对象
    python--基础知识点梳理(一)数据类型、迭代生成装饰器、函数
    java 集合
  • 原文地址:https://www.cnblogs.com/happyguy/p/14868518.html
Copyright © 2011-2022 走看看