• CF848D Shake It!


    Link
    我们考虑dp,设(f_{i,j})表示进行(i)次操作后Mincut为(j)的方案数。
    转移与背包类似,考虑枚举成对的(f)进行转移,对于(f_{i,j}),我们枚举(f_{a,b},f_{c,d}),使得(f_{i,j})(s)(f_{a,b})(s)重合,(f_{a,b})(t)(f_{c,d})(s)重合,(f_{c,d})(t)(f_{i,j})(t)重合,然后再枚举添加(x)(f_{a,b}-f_{c,d})
    这样就有:(f_{i,j}{f_{a,b}f_{c,d}+x-1choose x} ightarrow f_{i+x(a+c+1),j+xmin(b,d)})
    这样做的时间复杂度是(O(n^6log n))(枚举(x)的复杂度为调和级数),无法接受。
    考虑优化,设(g_{i,j}=sumlimits[a+c+1=iwedgemin(b,d)=j]f_{a,b}f_{c,d}),这样我们就可以先求出(g_{i,j})再更新(f_{i,j}),时间复杂度为(O(n^4log n)),非常优秀。

    #include<cstdio>
    #include<cstring>
    const int N=57,P=1000000007;
    void mod(int&x){x-=P,x+=x>>31&P;}
    int mul(int a,int b){return 1ll*a*b%P;}
    int f[N][N],g[N][N],t[N][N],inv[N];
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m),inv[0]=inv[1]=f[0][1]=1;
        for(int i=2;i<=n;++i) inv[i]=mul(inv[P%i],P-P/i);
        for(int i=1;i<=n;++i)
    	for(int j=1;j<=i+1;++j)
    	{
    	    for(int k=0;k<=i-1;++k)
    	    {
    		for(int l=j;l<=k+1;++l) mod(g[i][j]+=mul(f[k][l],f[i-1-k][j]));
    		for(int l=j+1;l<=i-k;++l) mod(g[i][j]+=mul(f[k][j],f[i-1-k][l]));
    	    }
    	    memset(t,0,sizeof t);
    	    for(int k=0;k<=n;++k) for(int p=1;p<=k+1;++p) for(int q=1,s=1;k+q*i<=n;++q) s=mul(mul(s,g[i][j]+q-1),inv[q]),mod(t[k+q*i][p+q*j]+=mul(f[k][p],s));
    	    for(int k=0;k<=n;++k) for(int l=1;l<=k+1;++l) mod(f[k][l]+=t[k][l]);
    	}
        printf("%d",f[n][m]);
    }
    
  • 相关阅读:
    Jinja2模板引擎简介
    单元测试
    Blueprint属性
    状态保持中的cookie
    异常捕获abort方法
    数据库迁移
    Flask-SQLAlchemy中 ORM 一对多的模型关系定义步骤
    request请求的常用属性
    搜索引擎
    Mark
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12252235.html
Copyright © 2020-2023  润新知