zoukankan      html  css  js  c++  java
  • bzoj4584: [Apio2016]赛艇

    真的是无尽接近单刷这题啊。。。。或许这就是差距吧,把大概的思路方向想出来具体就不会了

    心态爆炸

    首先可以一眼的是这个权值肯定要离散化,然后把每个选择的区间断成一段段

    假如枚举到当前学校当前区间,前一个学校比这个区间小的傻子都会转移,主要是处理同区间的转移

    我们可以先列一个方程的雏形:f[i][j]表示第i个学校的第j个区间 f[i][j]= ∑∑f[i'][j'](i'<i,j'<j) + cost

    可以发现cost是和区间长L和当前联续了几个区间k有关的:

    假如现在只连续了两个区间,那么手推一下就可以发现第二个区间的第1个数没有匹配的,第二个区间的第2个数有1个匹配的……

    一般的,有s1,all=1,si,j=∑si-1,j'(j'<j)这是一个不断算前缀和的过程,cost=sk,L*D 其中D是一个常数

    假如打表或者是手推一下,si,j=si-1,j-1+si,j-1 这个长得有点像组合数的递推式,然后其实它就是一个竖下来的杨辉三角形

    其实这个东西的现实意义就是n个学校选1~L的数,选出单调上升的方案数,那么其实相当于在L个数选n个排成一列

    对于连续了k个区间转移到k+1,那么其实是D*si,L=>D*si+1,L,相当于乘一个(L-k+1)/k,就可以了

    那么f[i][j][k]=∑∑f[i'][j'][k-1]*(L-k+1)/k

    特殊处理f[i][j][1]=∑∑∑f[i'][j'][k],这个要拿个数组搞

    这样加加优化就可以A了,然而其实我们可以不管这个k

    f[i][j]=∑∑f[i'][j']*cost(p)

    i倒着枚举,其中p表示枚举到当前有多少个学校涵盖当前区间,cost(p)=∑C(L,p-t)*C(p-1,p-t-1),意思是先选出p-t个出来,第p个学校必须选,其他可选可不选,再把它分配下去

    然后这个cost也等于C(L+p-1,p)假如选到了加进去的p-1个,相当于对应的学校不选,选出p个

    我们再让j一维取前缀和,就可以省一个for,那么就完成了

    把i和j的枚举顺序反过来,先得到区间长外面预处理组合数,用类似背包的做法数组还可以省掉一维j

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    const LL mod=1e9+7;
    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;
    }
    
    LL inv[1100];
    void init(){inv[1]=1;for(int i=2;i<=1000;i++)inv[i]=inv[mod%i]*(mod-mod/i)%mod;}
    LL updC(LL c,LL n,LL m)//C(n,m)=>C(n+1,m+1) 
    {
        return (c+c*(n-m)%mod*inv[m+1]%mod)%mod;
    }
    
    int le[510],re[510],lslen,ls[1100];
    LL f[1100],c[1100];
    int main()
    {
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
        int n;init();
        n=read();lslen=0;
        for(int i=1;i<=n;i++)
        {
            le[i]=read(),re[i]=read(),re[i]++;
            ls[++lslen]=le[i],ls[++lslen]=re[i];
        }
        sort(ls+1,ls+lslen+1);
        lslen=unique(ls+1,ls+lslen+1)-ls-1;
        for(int i=1;i<=n;i++)
            le[i]=lower_bound(ls+1,ls+lslen+1,le[i])-ls,
            re[i]=lower_bound(ls+1,ls+lslen+1,re[i])-ls;
        
        memset(f,0,sizeof(f));
        for(int j=1;j<=lslen;j++)f[0]=1;
        for(int j=1;j<=lslen;j++)
        {
            LL L=ls[j]-ls[j-1];
            c[1]=L;for(int i=1;i<=n;i++)c[i+1]=updC(c[i],L+i-1,i);
            for(int i=n;i>=1;i--)
            {
                if(le[i]+1<=j&&j<=re[i])
                {
                    int p=1;
                    for(int k=i-1;k>=0;k--)
                    {
                        f[i]=(f[i]+f[k]*c[p])%mod;
                        if(le[k]<j&&j<=re[k])p++;
                    }
                }
            }
        }
        LL ans=0;
        for(int i=1;i<=n;i++)ans=(ans+f[i])%mod;
        printf("%lld
    ",ans);
        
        return 0;
    }
  • 相关阅读:
    [PHP]解决PHP Call to undefined function ldap_connect()
    [Nginx] Nginx配置PHP应用传递PATH_INFO变量
    [PHP]解决PHP Fatal error: Call to undefined function mcrypt_get_iv_size()
    [CentOS] centos下安装最新稳定版nginx
    [CentOS]查看centos的发行版本情况
    [MySQL]创建用户并指定某一数据库权限
    [PHP] 安装memcached扩展
    [http]301和302的区别
    [javascript] 报错SecurityError: Failed to read the 'localStorage' property from 'Window': Access is denied for this document.
    [GO项目]开源免费在线客服系统-真正免费开源-GOFLY0.3.5发布-极简强大Go语言开发WEB网页客服
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/10216936.html
Copyright © 2011-2022 走看看