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; }