zoukankan      html  css  js  c++  java
  • 【BZOJ2159】Crash的文明世界 斯特林数+树形dp

    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

    Sol

    (x^n)可以用第二类斯特林数和(A^j_i)来表示,(A^j_i)又可以用(C_i^j*j!)表示,而(C(i,j)=C(i-1,j-1)+C(i-1,j)),因为有这个式子,我们可以围绕组合数递推公式来进行(dp)

    (down[x][i])表示(x)的子树对(x)的贡献,(up[x][i])表示除了(x)子树外的节点对(x)的贡献。设(v)(x)的儿子,容易推出:

    $down[x][k]=down[x][k]+down[v][k]+down[v][k-1] $

    $up[x][k]=up[x][k]+up[fa][k]+up[fa][k-1] $

    $up[x][k]=up[x][k]+down[fa][k]+down[fa][k-1] $

    $up[x][k]=up[x][k]-down[x][k]-down[x][k-1] $

    $up[x][k]=up[x][k]-down[x][k-1]-down[x][k-2] $

    (up)的最后两个递推式减去的分别是(x)的子树对(up[fa,k])(up[fa,k-1])的贡献。

    Code

    #include <bits/stdc++.h>
    using namespace std;
    int S[205][205],F[205],U[100005][205],D[100005][205],n,m,L,now,tmp,x,y,A,B,Q,M=10007;vector<int>e[100005];
    void dfs1(int x,int fa)
    {
        D[x][0]=1;for(int i=0;i<e[x].size();i++) if(e[x][i]!=fa)
        {
            dfs1(e[x][i],x);D[x][0]+=D[e[x][i]][0];
            for(int j=1;j<=m;j++) D[x][j]=(D[x][j]+D[e[x][i]][j]+D[e[x][i]][j-1])%M;
        }
    }
    void G(int x,int fa){for(int j=1;j<=m;j++) U[x][j]=(U[x][j]+U[fa][j]+U[fa][j-1]+D[fa][j]+D[fa][j-1]-D[x][j]-D[x][j-1]-D[x][j-1]-D[x][j-2]+10*M)%M;}
    void dfs2(int x,int fa){if(fa) U[x][0]=n-D[x][0],G(x,fa);for(int i=0;i<e[x].size();i++) if(e[x][i]!=fa) dfs2(e[x][i],x);}
    int main()
    {
        scanf("%d%d%d%d%d%d%d",&n,&m,&L,&now,&A,&B,&Q);
        for(int i=1;i<n;i++) now=(now*A+B)%Q,tmp=i<L?i:L,x=i-now%tmp,y=i+1,e[x].push_back(y),e[y].push_back(x);
        S[0][0]=F[0]=1;for(int i=1;i<=m;F[i]=F[i-1]*i%M,i++) for(int j=1;j<=i;j++) S[i][j]=(S[i-1][j]*j%M+S[i-1][j-1])%M;
        dfs1(1,0);dfs2(1,0);
        for(int i=1,A=0;i<=n;printf("%d
    ",A),i++,A=0) for(int j=1;j<=m;j++) A=(A+1ll*S[m][j]*F[j]%M*(U[i][j]+D[i][j])%M)%M;
    }
    
  • 相关阅读:
    PHPStrom 设置终端字体大小
    PostgreSQL 9 夸库查询
    弹性布局
    sql中的 where 、group by 和 having 用法解析
    数据库面试中常问的几个问题
    SQL中 UNION 和 UNION ALL 操作符小结
    SQL里 inner JOIN、 left (OUTER) JOIN 、right (OUTER) JOIN、 full (OUTER) JOIN 之间的区别
    MYSQL中LIMIT用法
    Java集合框架小结
    jQuery$.each循环遍历详解,各种取值对比,$.each遍历数组、对象、Dom元素、二维数组、双层循坏、类json数据等等
  • 原文地址:https://www.cnblogs.com/CK6100LGEV2/p/9425019.html
Copyright © 2011-2022 走看看