标签:tor lld 乘法 else end inf com freopen 个数
直接换根dp
f[i]表示,i为根的子树的方案
f[i]=Π(f[son]+1)(就是考虑这个边修不修(不修,子树中只有一种方案))
这里是乘法
换根的时候,直接算的话,为了消除x对fa的贡献,要乘上逆元
但是
1.会TLE
2.可能f[x]+1=1e9+7,也就是没有逆元(除以0是非法的)
所以考虑用x前面的兄弟的答案和后面兄弟答案(两个连乘积)拼凑
(不用每个点开一个vector记录儿子,直接每个x开一个数记录关于father的前后兄弟答案即可)
换根的时候,把fa的贡献随便作为x儿子y的前面兄弟或者后面兄弟即可
代码:
#include<bits/stdc++.h> #define il inline #define reg register int #define numb (ch^‘0‘) #define int long long using namespace std; typedef long long ll; il void rd(int &x){ char ch;bool fl=false; while(!isdigit(ch=getchar()))(ch==‘-‘)&&(fl=true); for(x=numb;isdigit(ch=getchar());x=x*10+numb); (fl==true)&&(x=-x); } namespace Miracle{ const int N=1e6+6; const int mod=1e9+7; int n; struct node{ int nxt,to; }e[2*N]; int hd[N],cnt; void add(int x,int y){ e[++cnt].nxt=hd[x]; e[cnt].to=y; hd[x]=cnt; } int f[N]; int ple[N],pri[N]; int ans[N]; int mo(int x){ //return x>=mod?x-mod:x; return x%mod; } int sta[N],top; void dfs(int x,int fa){ f[x]=1; int st=top; ll tmp=1; ple[x]=1; for(reg i=hd[x];i;i=e[i].nxt){ int y=e[i].to; if(y==fa) continue; dfs(y,x); sta[++top]=y; ple[y]=f[x]; f[x]=(ll)f[x]*(f[y]+1)%mod; } pri[x]=1; for(reg i=top;i>=st+1;--i){ pri[sta[i]]=tmp; tmp=(ll)tmp*(f[sta[i]]+1)%mod; } top=st; } void sol(int x,int fa){ if(x!=1){ ll nle=1; //cout<<" x "<<x<<" : "<<f[x]<<" ple "<<ple[x]<<" pri "<<pri[x]<<endl; f[x]=(ll)f[x]*((ll)ple[x]*pri[x]%mod+1)%mod; ans[x]=f[x]; nle=((ll)ple[x]*pri[x]%mod+1)%mod; //cout<<" x "<<x<<" : "<<nle<<endl; for(reg i=hd[x];i;i=e[i].nxt){ int y=e[i].to; if(y==fa) continue; ple[y]=(ll)ple[y]*nle%mod; sol(y,x); } } else{ ll nle=1; for(reg i=hd[x];i;i=e[i].nxt){ int y=e[i].to; if(y==fa) continue; sol(y,x); } } } int main(){ rd(n); int y; for(reg i=2;i<=n;++i){ rd(y);add(i,y);add(y,i); } dfs(1,0); ans[1]=f[1]; sol(1,0); for(reg i=1;i<=n;++i){ printf("%lld ",ans[i]); } return 0; } } signed main(){ freopen("2.in","r",stdin); freopen("2.out","w",stdout); Miracle::main(); return 0; } /* Author: *Miracle* Date: 2019/2/9 10:35:35 */
换根的时候往往可能会除以0
要警惕!
前后兄弟处理无疑是最好的方法。
标签:tor lld 乘法 else end inf com freopen 个数
原文地址:https://www.cnblogs.com/Miracevin/p/10358462.html