[Gdgzezoi]問題B:簡単な質問の多くの簡単な問題

説明
質問高橋にある日、青木:

  • ツリー所与はN個のノードを有し、1からKに整数がこれらのノードN数字エッジは、整数対(AI、BI)として表現されます。
  • 点Sのセットのために、我々は、F(S)Sを定義するすべてのノードの最小のサブツリーを含むノードの数を表す。(サブツリーは、元のツリーの接続されたサブグラフとして定義されます)
  • 私たちは、ツリー全体のプログラムでK・ノードを選択(NK)の種を持っている。これらのプログラムのすべてのために、我々はSで選択したノードの集合、あなたはF(S)のセット全て(NK)を見つけるを意味し、 924 844 033(素数)剰余への答え。

彼が取得することを決定するように高橋は、愚かな質問を感じるK = 1,2、⋯すべての答えのN。
入力
整数の最初の行のN、二つの整数のN-1次線がAI、BI。

出力
する際数K = I取得I応答モード924844033 N行は、i番目の行を表す。
サンプル入力
サンプルINPUT 1:
3
1 2
2 3

サンプル入力2:
4
1 2
1 3
1 4

サンプル入力3:
7
1 2
2 3
2 4
4
4 6
6 7
サンプル出力
サンプル出力1:
3
7
3

出力例2:
4
15
13
4

サンプル出力3:
7
67
150
179
122
45
7
HINT

試料1際に回答図としてK = 2。

データが満たされています:

  • 2≤N≤2×105
  • 1≤ai、bi≤N
  • ツリーは、図に示されています。

会うn≤2700に27程度のポイントがあります。

思考

第1の再撥容量の各点の寄与を考慮して明らかである、それは各xΣmk= 1(CKX)の要求、となる。ここで、m = 2 *(n-1)は、CKは各エッジの両側の子であります木のサイズ。

そう一緒に結合同じCK後、Σnk= 1つのCK(K / X)= 1 / X!ΣKのCKK!/(K-X)となる、ck≤nを指摘!

直接ラインに畳み込み、NTTあることが判明。

コード

#include<bits/stdc++.h>
#define ll long long
#define N 800077
#define mod 924844033
#define G 5
#define unG 554906420
using namespace std;
int n;
struct edge{int v,nxt;}e[N<<1];
int hd[N],cnt;
inline void add(int u, int v){e[++cnt]=(edge){v,hd[u]}, hd[u]=cnt;}
int power(int x, int y)
{
    int ret=1;
    while(y)
    {
        if(y&1) ret=(ll)ret*x%mod;
        x=(ll)x*x%mod;
        y>>=1;
    }
    return ret;
}
int siz[N],num[N];
void dfs(int u, int fa){
    siz[u]=1;
    for(int i=hd[u]; i; i=e[i].nxt) if(e[i].v!=fa){
        dfs(e[i].v,u);
        siz[u]+=siz[e[i].v];
        --num[siz[e[i].v]], --num[n-siz[e[i].v]];
    }
}
int fac[N],unfac[N];
int a[N],b[N],c[N];
struct Poly
{
    int n,bit,r[N];
    void init(int x)
    {
        for(n=1, bit=0; n<=x; n<<=1, ++bit);
        for(int i=1; i<n; ++i) r[i] = (r[i>>1]>>1) | ((i&1)<<(bit-1));
    }
    void dft(int *a, int f)
    {
        for(int i=0; i<n; ++i) if(i<r[i]) swap(a[i],a[r[i]]);
        for(int i=1; i<n; i<<=1)
        {
            int wn = power(f==1 ? G : unG, (mod-1)/(i<<1));
            for(int j=0; j<n; j+=(i<<1)){
                int w=1, x, y;
                for(int k=0; k<i; ++k, w=(ll)w*wn%mod)
                    x=a[j+k], y=(ll)w*a[j+i+k]%mod,
                    a[j+k]=(x+y)%mod, a[j+i+k]=(x-y+mod)%mod;
            }
        }
        if(f==-1)
        {
            int tmp=power(n,mod-2);
            for(int i=0; i<n; ++i) a[i]=(ll)a[i]*tmp%mod;
        }
    }
}NTT;
int main()
{
    scanf("%d",&n);
    for(int i=1,u,v; i<n; ++i) scanf("%d%d",&u,&v),add(u,v),add(v,u);
    fac[0]=1;
    for(int i=1; i<=n; ++i) fac[i]=(ll)fac[i-1]*i%mod;
    unfac[n]=power(fac[n],mod-2);
    for(int i=n-1; i>=0; --i) unfac[i]=(ll)unfac[i+1]*(i+1)%mod;
    dfs(1,0);
    num[n]=n;
    for(int i=0; i<=n; ++i)
        b[i]=((ll)num[n-i]*fac[n-i]%mod+mod)%mod,
        c[i]=unfac[i];
    NTT.init(n*2+1), NTT.dft(b,1), NTT.dft(c,1);
    for(int i=0; i<NTT.n; ++i) a[i]=(ll)b[i]*c[i]%mod;
    NTT.dft(a,-1);
    for(int i=1; i<=n; ++i) printf("%lld\n",(ll)a[n-i]*unfac[i]%mod);
}


703元記事公開 ウォンの賞賛392 ビューに14万+を

おすすめ

転載: blog.csdn.net/Eric1561759334/article/details/100786759