BZOJ4770: 图样

我们令f[n][k]表示n个点,每个点点权在[0,2k+1),MST边权和的期望
转移的时候,我们枚举有i个点第k位为1,n-i个点第k位为0,则最后的MST一定是i个点和n-i个点之间连一条边,剩下i个点,n-i个点个组成一棵生成树,而这个可以被划分成子问题
现在的问题在于i个点和n-i个点之间连一条边,这条边一定是i(n-i)条边里面最小的,那么这条边边权的期望怎么算
我们令g[n][m][k]表示n个点和m个点之间连一条边,每个点点权在[0,2k+1)间,nm条边里最小的那条边边权的期望,那么上面的期望就是2k+g[i][ni][k1]

g仍然不能直接dp,还需要一个辅助的状态
我们令h[n][m][k][l]表示每个点点权在[0,2k+1)间,n个点和m个点之间连的所有边边权都>=l的概率
转移的时候仍然枚举各自有多少个点在第k位为1,有

h[n][m][k][l]=x,yCnxCmy2n+mh[x][y][k1][l]h[nx][my][k1][l]h[x][my][k1][l2k]h[nx][y][k1][l2k]
(边界要注意一下)

dp出h后,有

g[n][m][k]=l>0h[n][m][k][l]

然后有

f[n][k]=iCni2n(f[i][k1]+f[ni][k1]+(g[i][ni][k1]+2k)[i(ni)>0])

复杂度O(n4m2m),完全不知道怎么过,但是因为nm不大,可以把所有f[n][m]打个表预处理出来

code(用来打表的程序):

#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;

const int maxn = 55;
const int maxk = 8;
const int mod  = 258280327;
inline void add(int &a,const int &b){a+=b;if(a>=mod)a-=mod;}

int pw(int x,int k)
{
    int re=1;
    for(;k;k>>=1,x=(ll)x*x%mod) if(k&1)
        re=(ll)re*x%mod;
    return re;
}
int inv(int x){ return pw(x,mod-2); }

int n,m;
int C[maxn][maxn],inv2[maxn];
int f[maxn][maxk],g[maxn][maxn][maxk],h[maxn][maxn][maxk][1<<maxk];

void dph()
{
    for(int i=1;i<=n;i++) for(int j=1;i+j<=n;j++)
        h[i][j][0][1]=inv2[i+j-1];
    for(int k=1;k<m;k++)
    {
        for(int i=1;i<=n;i++) for(int j=1;i+j<=n;j++)
        {
            for(int l=1;l<(1<<k+1);l++)
            {
                for(int x=0;x<=i;x++) for(int y=0;y<=j;y++)
                {
                    int p=(ll)C[i][x]*C[j][y]%mod;
                    if(x&&y) p=(ll)p*h[x][y][k-1][l]%mod;
                    if(i-x&&j-y) p=(ll)p*h[i-x][j-y][k-1][l]%mod;
                    if(x&&j-y&&(1<<k)<l) p=(ll)p*h[x][j-y][k-1][l-(1<<k)]%mod;
                    if(i-x&&y&&(1<<k)<l) p=(ll)p*h[i-x][y][k-1][l-(1<<k)]%mod;
                    add(h[i][j][k][l],p);
                }
                h[i][j][k][l]=(ll)h[i][j][k][l]*inv2[i+j]%mod;
            }
        }
    }
}
void dpg()
{
    for(int i=1;i<=n;i++) for(int j=1;i+j<=n;j++) for(int k=0;k<m;k++)
        for(int l=1;l<(1<<k+1);l++) add(g[i][j][k],h[i][j][k][l]);
}
void dpf()
{
    for(int i=1;i<=n;i++) 
    {
        for(int j=0;j<=i;j++)
        {
            int p=C[i][j],c=0;
            if(j&&i-j) c=1;
            add(f[i][0],p*c);
        }
        f[i][0]=(ll)f[i][0]*inv2[i]%mod;
    }
    for(int k=1;k<m;k++)
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<=i;j++)
            {
                int p=C[i][j],c=0;
                if(j&&i-j) c=g[j][i-j][k-1]+(1<<k);
                if(j) add(c,f[j][k-1]);
                if(i-j) add(c,f[i-j][k-1]);
                add(f[i][k],(ll)p*c%mod);
            }
            f[i][k]=(ll)f[i][k]*inv2[i]%mod;
        }
    }
}

int main()
{
    freopen("tmp.in","r",stdin);
    freopen("tmp.out","w",stdout);

    //scanf("%d%d",&n,&m);
    n=50; m=8;

    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-1]+C[i-1][j])%mod;
    }
    inv2[0]=1,inv2[1]=(mod+1)>>1;
    for(int i=2;i<=n;i++) inv2[i]=(ll)inv2[i-1]*inv2[1]%mod;

    dph();
    dpg();
    dpf();

    for(int i=1;i<=n;i++) for(int j=0;j<m;j++) printf("%d,",f[i][j]);

    return 0;
}
阅读更多
版权声明:...............转载说一声并注明出处qaq............... https://blog.csdn.net/L_0_Forever_LF/article/details/80251677
个人分类: BZOJ DP 期望
相关热词: bzoj4770
上一篇BZOJ5308: [Zjoi2018]胖
下一篇UOJ#273. 【清华集训2016】你的生命已如风中残烛
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭