LOJ#3124. 「CTS2019 | CTSC2019」氪金手游 容斥+DP
神仙容斥+DP可还行.
code:
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#define N 1007
#define ll long long
#define mod 998244353
#define pb push_back
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
int n,a[N][4],size[N<<2],f[N][N<<2],tmp[N<<2];
struct Edge {
int ty,v;
Edge(int ty=0,int v=0):ty(ty),v(v){}
};
vector<Edge>G[N];
int qpow(int x,int y) {
int tmp=1;
for(;y;y>>=1,x=(ll)x*x%mod) {
if(y&1) tmp=(ll)tmp*x%mod;
}
return tmp;
}
inline int get_inv(int x) {
return qpow(x,mod-2);
}
inline int ADD(int x,int y) {
return (x+y)>=mod?x+y-mod:x+y;
}
inline int DEC(int x,int y) {
return (x-y)<0?(x-y+mod):x-y;
}
void dfs(int x,int ff) {
size[x]=3;
f[x][1]=a[x][1],f[x][2]=a[x][2],f[x][3]=a[x][3];
for(int i=0;i<G[x].size();++i) {
Edge e=G[x][i];
if(e.v==ff) continue;
dfs(e.v,x);
int y=e.v;
for(int j=1;j<=size[x]+size[y];++j) {
tmp[j]=0;
}
if(e.ty==0) {
for(int j=1;j<=size[x];++j) {
for(int k=1;k<=size[y];++k) {
int cur=(ll)f[x][j]*f[y][k]%mod;
tmp[j+k]=DEC(tmp[j+k],cur);
tmp[j]=ADD(tmp[j],cur);
}
}
}
else {
for(int j=1;j<=size[x];++j) {
for(int k=1;k<=size[y];++k) {
tmp[j+k]=ADD(tmp[j+k],(ll)f[x][j]*f[y][k]%mod);
}
}
}
size[x]+=size[y];
for(int j=1;j<=size[x];++j) f[x][j]=tmp[j];
}
for(int i=1;i<=size[x];++i) f[x][i]=(ll)f[x][i]*get_inv(i)%mod;
}
int main() {
// setIO("input");
scanf("%d",&n);
int x,y,z;
for(int i=1;i<=n;++i) {
scanf("%d%d%d",&x,&y,&z);
ll s=x+y+z;
s=get_inv(s%(mod-2));
a[i][1]=(ll)x*s%mod;
a[i][2]=(ll)2*y%mod*s%mod;
a[i][3]=(ll)3*z%mod*s%mod;
}
for(int i=1;i<n;++i) {
scanf("%d%d",&x,&y);
G[x].pb(Edge(1,y));
G[y].pb(Edge(0,x));
}
dfs(1,0);
int ans=0;
for(int i=1;i<=size[1];++i) {
ans=ADD(ans,f[1][i]);
}
printf("%d\n",ans);
return 0;
}

浙公网安备 33010602011771号