[XOR最小生成树 期望 DP] BZOJ 4770 图样

30 篇文章 0 订阅
21 篇文章 0 订阅

首先感谢带我飞的rxd大爷

然后是 myh的题解 orzz
实现起来有点细节要处理 可能是我太弱?

这里写图片描述

我就这么写了个记忆化搜索 结果极限数据要3.5s
然后我就活生生的被卡常了

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define read(x) scanf("%d",&(x))
using namespace std;
typedef long long ll;

const int P=258280327;
const int N=51,M=9;
const int MP=10000;

ll C[N][N],pw[MP];

inline void Pre(int n){
  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])%P;
  }
  pw[0]=1;
  for (int i=1;i<MP;i++) pw[i]=(pw[i-1]<<1)%P;
}

inline ll Pow(ll a,int b){
  ll ret=1; for (;b;b>>=1,a=a*a%P) if (b&1) ret=ret*a%P; return ret;
}

int _p[N][N][M][1<<M];
bool fp[N][N][M][1<<M];

inline ll p(int S,int T,int m,int K){
  if (fp[S][T][m][K]) return _p[S][T][m][K];
  if (K>=(1<<m)) return 0;
  if (m==1) return K==1?2:pw[S+T];
  if (K<=0) return pw[(S+T)*m];
  ll ans=0;
  for (int i=1;i<S;i++)
    for (int j=1;j<T;j++)
      ans+=(C[S][i]*C[T][j]%P)*(p(i,j,m-1,K)*p(S-i,T-j,m-1,K)%P)%P;
  for (int j=1;j<T;j++)
    ans+=(C[T][j]*p(S,j,m-1,K)%P*pw[(m-1)*(T-j)]%P)<<1;
  for (int i=1;i<S;i++)
    ans+=(C[S][i]*p(i,T,m-1,K)%P*pw[(m-1)*(S-i)]%P)<<1;
  ans+=p(S,T,m-1,K-(1<<(m-1)))<<1;
  ans+=p(S,T,m-1,K)<<1;
  return fp[S][T][m][K]=1,_p[S][T][m][K]=ans%P;
}

int _g[N][N][M];
bool fg[N][N][M];

inline ll g(int S,int T,int m){
  if (!m) return 0;
  if (fg[S][T][m]) return _g[S][T][m];
  ll ret=0;
  for (int k=1;k<(1<<m);k++)
    ret+=p(S,T,m,k);
  return fg[S][T][m]=1,_g[S][T][m]=ret%P;
}

int n,m;
ll f[M][N];

int main(){
  freopen("t.in","r",stdin);
  freopen("t.out","w",stdout);
  read(n); read(m); Pre(n);
  for (int i=1;i<=m;i++)
    for (int j=1;j<=n;j++){
      for (int k=1;k<j;k++)
    f[i][j]+=C[j][k]*(pw[(j-k)*(i-1)]*f[i-1][k]%P+pw[k*(i-1)]*f[i-1][j-k]%P+g(k,j-k,i-1)+pw[(j+1)*(i-1)])%P;
      (f[i][j]+=(f[i-1][j]<<1)%P)%=P;
    }
  printf("%d\n",f[m][n]*Pow(pw[m*n],P-2)%P);
  return 0;
}

没办法 打表一发 表略 O(∩_∩)O嘿嘿嘿~

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值