2 条题解
-
0

#include <cstdio> #include <vector> using namespace std; const int M = 100005; const int MOD = 1e9+7; #define int long long int read() { int x=0,f=1;char c; while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;} while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();} return x*f; } int n,d,f[M],g[M],g0[M],g1[M],cnt[M];vector<int> G[M]; struct mat { int a[2][2]; mat() {a[0][0]=a[1][0]=a[0][1]=a[1][1]=0;} mat operator * (const mat &b) const { mat r; for(int i=0;i<2;i++) for(int j=0;j<2;j++) for(int k=0;k<2;k++) r.a[i][k]=(r.a[i][k]+a[i][j]*b.a[j][k])%MOD; return r; } }A,F; void dfs1(int u,int fa) { cnt[u]=f[u]=g0[u]=g1[u]=g[u]=0; for(int v:G[u]) if(v^fa) { dfs1(v,u); if(!f[v]) cnt[u]++,g0[u]+=g[v]; else g1[u]+=g[v]; } f[u]=(cnt[u]>0); if(!f[u]) g[u]=g1[u]+1; else if(cnt[u]==1) g[u]=g0[u]; } void dfs2(int u,int fa) { cnt[u]=f[u]=g0[u]=g1[u]=g[u]=0; for(int v:G[u]) { if(!f[v]) cnt[u]++,g0[u]+=g[v]; else g1[u]+=g[v]; } f[u]=(cnt[u]>0); if(!f[u]) g[u]=g1[u]+1; else if(cnt[u]==1) g[u]=g0[u]; // if(f[u]==1) { F.a[0][1]++; A.a[0][0]=(A.a[0][0]+g[u])%MOD; A.a[0][1]=(A.a[0][1]+n-g[u])%MOD; A.a[1][1]=(A.a[1][1]+n)%MOD; } else { F.a[0][0]++; A.a[0][1]=(A.a[0][1]+g[u])%MOD; A.a[0][0]=(A.a[0][0]+n-g[u])%MOD; A.a[1][0]=(A.a[1][0]+n)%MOD; } // int tf=f[u],tg=g[u],tc=cnt[u]; for(int v:G[u]) if(v^fa) { if(!f[v]) { if(cnt[u]==1) cnt[u]=0,g[u]=g1[u]+1,f[u]=0; else//f[u]=1; { cnt[u]--; g[u]=(cnt[u]==1)?g0[u]-g[v]:0; } } else if(!f[u]) g[u]=g1[u]-g[v]+1; dfs2(v,u); f[u]=tf;g[u]=tg;cnt[u]=tc; } } signed main() { n=read();d=read()-1; for(int i=1;i<n;i++) { int u=read(),v=read(); G[u].push_back(v); G[v].push_back(u); } dfs1(1,0);dfs2(1,0); while(d>0) {if(d&1) F=F*A;A=A*A;d>>=1;} int ans=g[1]*F.a[0][0]%MOD; if(f[1]) ans=(n*(F.a[0][0]+F.a[0][1])-ans)%MOD; printf("%lld\n",(ans+MOD)%MOD); } -
0
E97 换根DP+矩阵加速 P6803 [CEOI 2020] 星际迷航

// 换根DP+矩阵加速 O(n+logD) #include <bits/stdc++.h> using namespace std; typedef long long LL; const int N=100005,M=1e9+7; vector<int> e[N]; int n; LL D,m,ans; int f[N],r[N],s[N],c[N][2]; void dfs(int x,int fa){ for(int y:e[x]){ if(y==fa) continue; dfs(y,x); s[x]+=!f[y]; //败点儿子的数量 c[x][f[y]]+=r[y]; //可逆点的数量 } f[x]=(s[x]>0); //若有败点儿子 则x为胜点 if(s[x]==0) r[x]=c[x][1]+1; //没有败点儿子 else if(s[x]==1) r[x]=c[x][0]; //只有一个败点儿子 else r[x]=0; //有多个败点儿子 } void dfs2(int x,int fa){ if(f[x]==0) ++m; for(int y:e[x]){ if(y==fa) continue; int fx=f[x],rx=r[x],sx=s[x],c0=c[x][0],c1=c[x][1]; s[x]-=!f[y]; //去掉y的贡献 c[x][f[y]]-=r[y]; f[x]=(s[x]>0); if(s[x]==0) r[x]=c[x][1]+1; else if(s[x]==1) r[x]=c[x][0]; else r[x]=0; s[y]+=!f[x]; //加上x的贡献 c[y][f[x]]+=r[x]; f[y]|=!f[x]; if(s[y]==0) r[y]=c[y][1]+1; else if(s[y]==1) r[y]=c[y][0]; else r[y]=0; dfs2(y,x); f[x]=fx,r[x]=rx,s[x]=sx,c[x][0]=c0,c[x][1]=c1; } } struct mat{ LL a[2][2]; mat(){memset(a,0,sizeof a);} mat operator*(const mat &x){ mat t; for(int i=0;i<2;i++) for(int j=0;j<2;j++) for(int k=0;k<2;k++) t.a[i][j]=(t.a[i][j]+a[i][k]*x.a[k][j])%M; return t; } }F,A; void qpow(LL n){ while(n){ if(n&1) F=A*F; A=A*A; n>>=1; } } void add(LL &a,LL b){a=(a+b)%M;} int main(){ scanf("%d%lld",&n,&D); for(int i=1,x,y;i<n;i++){ scanf("%d%d",&x,&y); e[x].push_back(y),e[y].push_back(x); } dfs(1,0); dfs2(1,0); //换根DP for(int i=1;i<=n;i++){ if(f[i]==0){ add(A.a[0][0],n-r[i]); add(A.a[0][1],n); add(A.a[1][0],r[i]); } else{ add(A.a[0][0],r[i]); add(A.a[1][0],n-r[i]); add(A.a[1][1],n); } } F.a[0][0]=m,F.a[1][0]=n-m; qpow(D-1); //矩阵加速 if(f[1]==0) ans=r[1]*F.a[0][0]%M; else ans=((n-r[1])*F.a[0][0]+n*F.a[1][0])%M; printf("%d\n",ans); }
- 1
信息
- ID
- 2411
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者