Hướng dẫn giải của TRIFT
Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
Đặt ~dp[i][j]~ là số lượng cây con gốc là ~i~ và mask là ~j~, ~mask[j] = 1~ nếu như mọi đỉnh trong cây con đó có bit ~j~ bật. Base là ~dp[i][mask[i]] = 1~.
Công thức chuyển: ~dp[u][j] = dp[u][j] + \sum_{k \neq j} dp[u][k] \times dp[v][l]~ với ~v~ là con trực tiếp của ~u~. Độ phức tạp: ~\mathcal{O} (N \times 4 ^ M) \rightarrow~ TLE.
Ta sẽ tối ưu bằng DP SOS. Cùng với công thức trên, với mỗi mask ~z~, đếm xem có bao nhiêu mask ~j~ và ~k~ mà ~j \& k = z~ theo ~dp[u][j]~ và ~dp[v][k]~.
Độ phức tạp: ~\mathcal{O}(M \times 2^M \times N)~.
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") #include<cstring> #include<cstdio> #include<algorithm> #include<iostream> #include<cmath> #include<queue> #include<set> #include<stack> #include<map> #include<bitset> #include<cassert> using namespace std; #define rep(i,l,r) for(int i=(l);i<=(r);++i) #define rpe(i,r,l) for(int i=(r);i>=(l);--i) #define rpp(i,x,e,head) for(int i=head[x];~i;i=e[i].next) #define dyes cerr<<"yes"<<endl #define debug(x) cerr<<#x<<"="<<x<<endl #define Debug(...) fprintf(stderr, __VA_ARGS__) #define pts puts("") typedef double db; typedef long long ll; typedef unsigned long long ull; inline int read(){ int f=1,x=0;char ch; do{ch=getchar();if(ch=='-')f=-1LL;}while(ch<'0'||ch>'9'); do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9'); return f*x; } inline ll readll(){ ll f=1,x=0;char ch; do{ch=getchar();if(ch=='-')f=-1LL;}while(ch<'0'||ch>'9'); do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9'); return f*x; } template <class T> inline void chmax(T &a,T b){if(a<b) a=b;} template <class T> inline void chmin(T &a,T b){if(a>b) a=b;} inline void swap(int &a,int &b){int c=a;a=b;b=c;} using namespace std; #define mst(a,val) memset(a,val,sizeof(a)) #define pii pair<int,int> #define piii pair<int,pair<int,int> > #define mp(i,j) make_pair(i,j) #define fi first #define sc second #define inf (0x3f3f3f3f) #define infl (0x3f3f3f3f3f3f3f3fLL) #define forvec(i,j) for(vector<int>::iterator i=j.begin();i!=j.end();++i) #define forvecv(i,j) for(vector<int>::iterator i=--j.end();i>=j.begin();--i) //=====================head end======================// const int N=5010; const int P=1e9+7; struct node{ int next,to; }e[N<<1]; int head[N],cnt; inline void add(int u,int v){ e[cnt].to=v;e[cnt].next=head[u];head[u]=cnt++; } int n,m,a[N]; int dp[N][(1<<10)+5]; inline ll inc(ll a,ll b){return a+b>=P ? a+b-P:a+b;} inline ll dec(ll a,ll b){return a>=b ? a-b:a-b+P;} inline void fwt(int *a,int f){ int n=(1<<m); for(int i=1;i<n;i<<=1){ for(int j=0,p=(i<<1);j<n;j+=p){ for(int k=0;k<i;++k){ ll x=a[j+k],y=a[j+k+i]; if(f==1){ a[j+k]=inc(x,y); }else{ a[j+k]=dec(x,y); } } } } } int S; int tmp[(1<<10)+5]; inline void dfs(int x,int f){ rep(i,0,S) if(((S^i)&(S^a[x]))==(S^a[x])) dp[x][i]=1; rpp(i,x,e,head){ int v=e[i].to;if(v==f) continue; dfs(v,x); rep(i,0,S) dp[x][i]=1LL*dp[x][i]*(1+dp[v][i])%P; } rep(i,0,S) tmp[i]=inc(tmp[i],dp[x][i]); } ll ans[11]; int main(){ int T=1; while(T --> 0){ mst(head,-1);cnt=0;n=read();m=read();rep(i,1,n-1){int u=read(),v=read();add(u,v);add(v,u);} mst(dp,0);mst(a,0);rep(i,1,n) rep(j,1,m) a[i]|=(read()<<(j-1)); S=(1<<m)-1; rep(i,0,S) tmp[i]=0; dfs(1,0);mst(ans,0); fwt(tmp,-1); rep(i,0,S) ans[__builtin_popcount(i)]=inc(ans[__builtin_popcount(i)],tmp[i]); rep(i,0,m) printf("%lld ",ans[i]); puts(""); } return 0; }
Bình luận