HDU 5552のバス路線

HDU 5552のバス路線

図環考える不都合は、通信非循環グラフの数と考えられ、次いで、図のような通信の数を差し引くことができます。

図非環式通信番号がツリーの数であり、そしてprufer配列我々は$ N ^ {N-2}を知っている $ による$ N-1 $側に順番におり、各側は、総非環状ので、塗装することができプログラム番号は、$ M ^ {N-1}であり 、N ^ {N-2} $

そして、連結グラフの数を考えます。この数は、より良い図の良好なコミュニケーションとはみなされません。

念頭に置いていた、それをカウントする方法を切断グラフの数は算入除外ですが、一見問題の不滅のアイデアへの解決策を見つけるために見て、実現しません。固定点を考慮して、この点は、通信ブロック、ランダム点も残りの部分は、必ずしも通信しないように接続されています。それはすべての場合で計算することが可能に漏れないように、そして、このことから、図中の最後のポイントでなければなりません。

$ Sは、(i)$ $を表すIポイントを$検討図でプログラムの総数$(M + 1)^ {ある \ FRAC {N(N + 1)} {2}} $、 $ \ FRACの合計{N(N + 1)} {2} $ 辺、$ M $次のエッジの色を選択したりすることができません。

F $(I)$を考える図通信$ I $ポイントの実施形態を表します。

$ F(N)= G(N) - \ displaystyle \ sum_ {i = 1} ^ N \ binom {I-1} {N-1} F(I)G(NI)$

これは非常にNTTパーティションを探します

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define ll long long
using namespace std;
#define P 152076289
#define MAXN (1 << 19) + 13
int n , m;
int a[MAXN];
int Pow(int x,int y) {
    int res=1;
    while(y) {
        if(y&1) res=res*(ll)x%P;
        x=x*(ll)x%P,y>>=1;
    }
    return res;
}
int wn[2][MAXN];
void getwn(int l) {
    for(int i=1;i<(1<<l);i<<=1) {
        int w0=Pow(106,(P-1)/(i<<1)),w1=Pow(106,P-1-(P-1)/(i<<1));
        wn[0][i]=wn[1][i]=1;
        for(int j=1;j<i;++j)
            wn[0][i+j]=wn[0][i+j-1]*(ll)w0%P,
                    wn[1][i+j]=wn[1][i+j-1]*(ll)w1%P;
    }
}
int rev[MAXN];
void getr(int l) { for(int i=1;i<(1<<l);++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<l-1); }
void NTT(int *A,int len,int f) {
    for(int i=0;i<len;++i) if(rev[i]<i) swap(A[i],A[rev[i]]);
    for(int l=1;l<len;l<<=1)
        for(int i=0;i<len;i+=(l<<1))
            for(int k=0;k<l;++k) {
                int t1=A[i+k],t2=A[i+l+k]*(ll)wn[f][l+k]%P;
                A[i+k]=(t1+t2)%P;
                A[i+l+k]=(t1-t2+P)%P;
            }
    if( f == 1 ) for(int inv=Pow(len,P-2),i=0;i<len;++i) A[i]=A[i]*(ll)inv%P;
}
int f[MAXN];
int A[MAXN] , B[MAXN];
int J[MAXN] , invJ[MAXN] , s[MAXN];
void CDQ(int *a,int *b,int l,int r){
    if( l == r ) { a[l] += s[l] , a[l] %= P; return; }
    int m = l + r >> 1;
    CDQ( a , b , l , m );
    int p = 1 , len = 0;
    while( p <= ( r - l + 1 ) * 2 ) p <<= 1 , ++ len;
    getr( len ) , getwn( len );
    for( int i = 0 ; i < p ; ++i ) A[i] = B[i] = 0;
    for( int i = l ; i <= m ; ++i ) A[i - l] = 1ll * a[i] * invJ[i - 1] % P;
    for( int i = 0 ; i <= r - l ; ++i ) B[i] = 1ll * s[i] * invJ[i] % P;
    NTT( A , p , 0 ) , NTT( B , p , 0 );
    for( int i = 0 ; i < p ; ++i ) A[i] = 1ll * A[i] * B[i] % P;
    NTT( A , p , 1 );
    for( int i = m + 1 ; i <= r ; ++i ) a[i] = ( a[i] - 1ll * J[i - 1] * A[i-l] % P + P ) % P;
    CDQ( a , b , m + 1 , r );
}
int kase = 0;
signed main() {
    J[0] = invJ[0] = 1;
    for( int i = 1 ; i < MAXN ; ++ i ) 
        J[i] = 1ll * J[i - 1] * i % P , invJ[i] = Pow( J[i] , P - 2 );
    int T;cin >> T;
    while( T --> 0 ) {
        cin >> n >> m; m %= P;
        memset( f , 0 , sizeof f ) , memset( s , 0 , sizeof s );
        for( int i = 1 ; i <= n ; ++ i ) 
            s[i] = Pow( m + 1 , 1ll * i * ( i - 1 ) / 2 % ( P - 1 ) );
        f[0] = 1;
        CDQ( f , a , 0 , n );
        int x;
        printf("Case #%d: %d\n",++ kase,( f[n] - 1ll * Pow(n, n - 2) * Pow(m, n - 1) % P + P) % P);
    }
}

おすすめ

転載: www.cnblogs.com/yijan/p/hdu5552.html