zoukankan      html  css  js  c++  java
  • 【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, k);
    for (i = 1; i < N; i ++)
    {
    now = (now * A + B) % Q;
    tmp = (i < L) ? i : L;
    fprintf(outfile, "%d %d ", 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}=displaystylesum_{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为根的子树中,sumlimits_{v在i的子树中}C_{dis(i,v)}^j)。然后我们转移的时候,根据(C_i^j=C_{i-1}^{j-1}+C_{i-1}^j)得到(f[i][j]=sumlimits_{uin 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<<"
    ";
    	}
    	return 0;
    }
    
  • 相关阅读:
    【Linux】项目部署
    【架构师之路】【MQ】消息队列
    【数据库】【Python】mysql
    【算法】【Python】找出字符串中重复出现的字符 并求出重复次数 且根据重复次数从大到小排列
    【Python】排序 按照list中的字典的某key排序
    Kettle Post请求webservice
    python+pytest+allure接口自动化测试框架
    Python+unittest+requests+htmlTestRunner+excel完整的接口自动化框架
    python实现栈的基本操作
    展示博客园顶部的随笔、文章、评论、阅读量统计数据
  • 原文地址:https://www.cnblogs.com/hchhch233/p/10008183.html
Copyright © 2011-2022 走看看