zoukankan      html  css  js  c++  java
  • BZOJ4584 APIO2016赛艇(动态规划+组合数学)

      如果值域不大,容易想到设f[i][j]为第i个学校选了j的方案数,枚举上一个学校是哪个选了啥即可,可以前缀和优化。于是考虑离散化,由于离散化后相同的数可能可以取不同的值,所以枚举第一个和其所选数(离散化后)相同的学校是哪个,考虑这一段里选几个学校怎么选数,组合数即可。各种显然的优化后即可做到O(n3),瞎卡卡常就……根本过不了。被卡常已经习惯了。不要把有限的生命投入无限的卡常之中。越菜的人越容易被卡常。——沃兹基硕德。luogu8s,darkbzoj40s,bzoj?s。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 510
    #define P 1000000007
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int n,a[N],b[N],f[N][N<<2],g[N][N<<2],C[N][N],c[N],h[N<<2][N],u[N<<2],v[N<<2],l[N<<2],r[N<<2],last[N][N<<2],tot[N<<2],t;
    void inc(int &x,int y){x+=y;if (x>=P) x-=P;}
    int inv(int a)
    {
        int s=1,k=P-2;
        for (;k;k>>=1,a=1ll*a*a%P) if (k&1) s=1ll*s*a%P;
        return s;
    }
    void pre()
    {
        sort(v+1,v+t+1);
        t=unique(v+1,v+t+1)-v-1;int t2=0;
        u[++t2]=v[1];l[t2]=r[t2]=v[1];
        for (int i=2;i<=t;i++)
        {
            if (v[i]-1!=v[i-1]) u[++t2]=v[i]-1,l[t2]=v[i-1]+1,r[t2]=v[i]-1;
            u[++t2]=v[i],l[t2]=v[i],r[t2]=v[i];
        }
        t=t2;memcpy(v,u,sizeof(v));
        for (int i=1;i<=n;i++) a[i]=lower_bound(v+1,v+t+1,a[i])-v,b[i]=lower_bound(v+1,v+t+1,b[i])-v;
        for (int i=1;i<=t;i++)
        {
            int l=0;
            for (int j=1;j<=n;j++)
            if (a[j]<=i&&i<=b[j]) last[j][i]=l,tot[i]++,l=j;
            else last[j][i]=0;
        }
    }
    void calc()
    {
        C[0][0]=1;
        for (int i=1;i<=n;i++)
        {
            C[i][0]=C[i][i]=1;
            for (int j=1;j<i;j++) C[i][j]=(C[i-1][j-1]+C[i-1][j])%P;
        }
        for (int i=1;i<=t;i++)
        {
            memset(c,0,sizeof(c));
            c[0]=1;
            for (int j=1;j<=n&&j<=r[i]-l[i]+2;j++)
            c[j]=1ll*c[j-1]*(r[i]-l[i]+1-j+1)%P*inv(j)%P;
            for (int j=2;j<=tot[i];j++)
                for (int p=2;p<=j;p++)
                inc(h[i][j],1ll*C[j-2][p-2]*c[p]%P);
        }
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj4584.in","r",stdin);
        freopen("bzoj4584.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read();
        for (int i=1;i<=n;i++) v[++t]=a[i]=read(),v[++t]=b[i]=read();
        pre();calc();
        f[0][0]=1;for (int i=0;i<=t;i++) g[0][i]=1;
        for (int i=1;i<=n;i++)
        {
            for (int j=a[i];j<=b[i];j++)
            {
                f[i][j]=1ll*g[i-1][j-1]*(r[j]-l[j]+1)%P;
                int cnt=1;
                for (int k=last[i][j];k;k=last[k][j])
                inc(f[i][j],1ll*g[k-1][j-1]*h[j][++cnt]%P);
            }
            for (int j=1;j<=t;j++) g[i][j]=(g[i][j-1]+f[i][j])%P;
            for (int j=0;j<=t;j++) inc(g[i][j],g[i-1][j]);
        }
        cout<<(g[n][t]+P-1)%P;
        return 0;
    }
  • 相关阅读:
    MFC Slider控件 去掉边上的虚线
    VC學習網址
    全局程序集缓存工具 (Gacutil.exe)
    滚动条集合
    调用 DialogBox 会失败解决方法
    全局程序集缓存GAC”是什么概念
    UltraVNC:超实用的远程控制工具(图)
    VC程序员之无法选择的命运
    C++类
    角色权限批量设置,随点!
  • 原文地址:https://www.cnblogs.com/Gloid/p/9899298.html
Copyright © 2011-2022 走看看