【bzoj 2159】Crash 的文明世界
Description
Crash小朋友最近迷上了一款游戏——文明5(Civilization V)。在这个游戏中,玩家可以建立和发展自己的国家,通过外交和别的国家交流,或是通过战争征服别的国家。现在Crash已经拥有了一个N个城市的国家,这些城市之间通过道路相连。由于建设道路是有花费的,因此Crash只修建了N-1条道路连接这些城市,不过可以保证任意两个城市都有路径相通。在游戏中,Crash需要选择一个城市作为他的国家的首都,选择首都需要考虑很多指标,有一个指标是这样的:S(i)=∑Nj=1dist(i,j)k。其中S(i)表示第i 个城市的指标值,dist(i, j)表示第i个城市到第j个城市需要经过的道路条数的最小值,k为一个常数且为正整数。因此Crash交给你一个简单的任务:给出城市之间的道路,对于每个城市,输出这个城市的指标值,由于指标值可能会很大,所以你只需要输出这个数 mod 10007 的值。
Input
输入的第一行包括两个正整数N和k。下面有N-1行,每行两个正整数u、v (1 ≤ u, v ≤ N),表示第u个城市和第v个城市之间有道路相连。这些道路保证能符合题目的要求。
Output
输出共N行,每行一个正整数,第i行的正整数表示第i个城市的指标值 mod 10007 的值。
用结论来化简式子:xn=∑ni=1S(n,i)⋅F(x,i)
S(n,i)为第二类斯特林数,F(x,i)=x!(x−i)!
可得:ans(i)=n∑j=1dist(i,j)m=n∑j=1m∑k=1S(m,k)⋅F(dist(i,j),k)=m∑k=1S(m,k)n∑j=1F(dist(i,j),k)=m∑k=1S(m,k)⋅k!⋅n∑j=1C(dist(i,j),k)
根据组合数递推公式:C(n,m)=C(n−1,m)+C(n−1,m−1) 就可以很方便的对后面的部分进行树形dp了。
具体地,令 up(x,i) 为不在 x 的子树中的部分的贡献,令 dn(x,i) 为 x 的子树的贡献。特别的,dn(x,0)=1。
详见代码。

1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #define LL long long 5 using namespace std; 6 const int N=5e4+5; 7 const int M=155; 8 const int mod=1e4+7; 9 int n,m,u,v,cnt,ans,tmp; 10 int first[N],fac[M],s[M][M]; 11 int up[N][M],dn[N][M]; 12 struct edge{int to,next;}e[N*2]; 13 int read() 14 { 15 int x=0,f=1;char c=getchar(); 16 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 17 while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} 18 return x*f; 19 } 20 void ins(int u,int v){e[++cnt]=(edge){v,first[u]};first[u]=cnt;} 21 void Mod(int& a,int b){a+=b;if(a>=mod)a-=mod;} 22 void dfs1(int x,int fa) 23 { 24 dn[x][0]=1; 25 for(int i=first[x];i;i=e[i].next) 26 { 27 int to=e[i].to; 28 if(to==fa)continue; 29 dfs1(to,x); 30 Mod(dn[x][0],dn[to][0]); 31 for(int j=1;j<=m;j++) 32 Mod(dn[x][j],(dn[to][j]+dn[to][j-1])%mod); 33 } 34 } 35 void dfs2(int x,int fa) 36 { 37 if(fa!=-1) 38 { 39 up[x][0]=n-dn[x][0]; 40 for(int i=1;i<=m;i++) 41 { 42 Mod(up[x][i],(up[fa][i]+up[fa][i-1])%mod); 43 Mod(up[x][i],(dn[fa][i]+dn[fa][i-1])%mod); 44 Mod(up[x][i],(2*mod-dn[x][i]-dn[x][i-1])%mod); 45 Mod(up[x][i],(mod-dn[x][i-1])%mod); 46 if(i!=1)Mod(up[x][i],(mod-dn[x][i-2])%mod); 47 } 48 } 49 for(int i=first[x];i;i=e[i].next) 50 if(e[i].to!=fa)dfs2(e[i].to,x); 51 } 52 int main() 53 { 54 int L,now,A,B,Q; 55 n=read();m=read();L=read(); 56 now=read();A=read();B=read();Q=read(); 57 for(int i=1;i<n;i++) 58 { 59 now=(now*A+B)%Q; 60 tmp=i<L?i:L; 61 u=i-now%tmp;v=i+1; 62 ins(u,v);ins(v,u); 63 } 64 // n=read();m=read(); 65 // for(int i=1;i<n;i++) 66 // { 67 // u=read();v=read(); 68 // ins(u,v);ins(v,u); 69 // } 70 fac[0]=s[0][0]=1; 71 for(int i=1;i<=m;i++) 72 { 73 fac[i]=fac[i-1]*i%mod; 74 for(int j=1;j<=i;j++) 75 s[i][j]=(s[i-1][j]*j+s[i-1][j-1])%mod; 76 } 77 dfs1(1,-1);dfs2(1,-1); 78 for(int i=1;i<=n;i++) 79 { 80 ans=0; 81 for(int j=1;j<=m;j++) 82 Mod(ans,s[m][j]*fac[j]%mod*(up[i][j]+dn[i][j])%mod); 83 printf("%d\n",ans); 84 } 85 return 0; 86 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术