【BZOJ2159】Crash的文明世界

【2011集训贾志鹏】Crash的文明世界

Description

  Crash小朋友最近迷上了一款游戏——文明5(Civilization V)。在这个游戏中,玩家可以建立和发展自己的国家,通过外交和别的国家交流,或是通过战争征服别的国家。
  现在Crash已经拥有了一个N个城市的国家,这些城市之间通过道路相连。由于建设道路是有花费的,因此Crash只修建了N-1条道路连接这些城市,不过可以保证任意两个城市都有路径相通。
  在游戏中,Crash需要选择一个城市作为他的国家的首都,选择首都需要考虑很多指标,有一个指标是这样的:
                  img
  其中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的值。

Sample Input

5 2
1 2
1 3
2 4
2 5

Sample Output

10
7
23
18
18

Hint

【数据规模和约定】
  20%的数据满足N ≤ 5000、k ≤ 30。
  50%的数据满足N ≤ 50000、k ≤ 30。
  100%的数据满足N ≤ 50000、k ≤ 150。
【特别说明】
  由于数据大小限制为5MB,我只好对测试时的输入文件进行压缩处理。下面的函数可以将压缩的输入文件转化为原始输入文件。(函数从infile中读入压缩的输入文件,将解压缩后的输入文件输出到outfile中)
C/C++版本:
void Uncompress(FILE *infile, FILE *outfile)
{
int N, k, L, i, now, A, B, Q, tmp;
fscanf(infile, "%d%d%d", &N, &k, &L);
fscanf(infile, "%d%d%d%d", &now, &A, &B, &Q);
fprintf(outfile, "%d %d\n", N, k);
for (i = 1; i < N; i ++)
{
now = (now * A + B) % Q;
tmp = (i < L) ? i : L;
fprintf(outfile, "%d %d\n", i - now % tmp, i + 1);
}
}

Pascal版本:
 procedure Uncompress(var infile, outfile : text);
  var
  N, k, L, i, now, A, B, Q, tmp : longint;
  begin
  read(infile, N, k, L, now, A, B, Q);
  writeln(outfile, N, ' ', k);
  for i := 1 to N - 1 do
  begin
  now := (now * A + B) mod Q;
  if i < L then tmp := i else tmp := L;
  writeln(outfile, i - now mod tmp, ' ', i + 1);
  end;
  end;

  下面给出一个具体的例子。civiliazation_compressed.in表示压缩的输入文件,civilization.in表示解压缩后的输入文件。
civilization_compressed.in
7 26 4
29643 2347 5431 54209
civilization.in
7 26
1 2
2 3
2 4
3 5
4 6
5 7

根据套路\(n^{k}=\displaystyle\sum_{i=0}^{k}C_{n}^{i}S_2(k,i)\cdot i!\)

\(S_2\)表示第二类斯特林数。然后我们拿\(i\)当下标,记录相同的\(i\)下,\(\sum C_{n}^{i}\)的值就行了。

然后我们做树形DP,\(f[i][j]表示以i为根的子树中,\sum\limits_{v在i的子树中}C_{dis(i,v)}^j\)。然后我们转移的时候,根据\(C_i^j=C_{i-1}^{j-1}+C_{i-1}^j\)得到\(f[i][j]=\sum\limits_{u\in son_i}f[u][j-1]+f[u][j]\)

代码:

#include<bits/stdc++.h>
#define ll long long
#define mod 10007
#define N 50005
 
using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}

int n,k;
ll fac[N];
ll ksm(ll t,ll x) {
	ll ans=1;
	for(;x;x>>=1,t=t*t%mod)
		if(x&1) ans=ans*t%mod;
	return ans;
}
struct load {int to,next;}s[N<<1];
int h[N],cnt;
void add(int i,int j) {s[++cnt]=(load) {j,h[i]};h[i]=cnt;}
int fa[N];
ll f[N][200];
ll sum[N][200];

void dfs(int v) {
	f[v][0]=1;
	for(int i=h[v];i;i=s[i].next) {
		int to=s[i].to;
		if(to==fa[v]) continue ;
		fa[to]=v;
		dfs(to);
		for(int j=1;j<=k;j++) (f[v][j]+=f[to][j]+f[to][j-1])%=mod;
		(f[v][0]+=f[to][0])%=mod;
	}
}

ll tem[200];
void solve2(int v) {
	for(int i=h[v];i;i=s[i].next) {
		int to=s[i].to;
		if(to==fa[v]) continue ;
		for(int j=1;j<=k;j++) {
			sum[to][j]=f[to][j];
			tem[j]=(sum[v][j]-f[to][j]-f[to][j-1]+2*mod)%mod;
		}
		sum[to][0]=f[to][0];
		tem[0]=sum[v][0]-f[to][0];
		for(int j=1;j<=k;j++) (sum[to][j]+=tem[j]+tem[j-1])%=mod;
		sum[to][0]+=tem[0];
		solve2(to); 
	}
}

ll s2[200][200];
int main() {
	n=Get(),k=Get();
	ll l=Get(),now=Get(),A=Get(),B=Get(),Q=Get();
	for(int i=1;i<n;i++) {
		now=(now*A+B)%Q;
		ll tem=i<l?i:l;
		add(i-now%tem,i+1);
	}
	fac[0]=1;
	for(int i=1;i<=n;i++) fac[i]=fac[i-1]*i%mod;
	s2[0][0]=1;
	for(int i=1;i<=k;i++) {
		for(int j=1;j<=k;j++) {
			s2[i][j]=(s2[i-1][j-1]+j*s2[i-1][j]%mod)%mod;
		}
	}
	dfs(1);
	for(int i=0;i<=k;i++) sum[1][i]=f[1][i];
	solve2(1);
	
	for(int i=1;i<=n;i++) {
		ll ans=0;
		for(int j=1;j<=k;j++) (ans+=sum[i][j]*s2[k][j]%mod*fac[j]%mod)%=mod;
		cout<<ans<<"\n";
	}
	return 0;
}
posted @ 2018-11-23 16:07  hec0411  阅读(606)  评论(0编辑  收藏  举报