首页 > 其他 > 详细

luoguP5591 【小猪佩奇学数学】

时间:2019-10-14 20:12:46      阅读:95      评论:0      收藏:0      [点我收藏+]

由于存在一道题叫做白兔之舞就导致这道题看上去非常的板......

约定,\([x]\)表示\(x\)向下取整

\[\sum_{i=0}^n\dbinom{n}{i}*p^i*[\dfrac{i}{k}]\]

然后会想到可以将\([\dfrac{i}{k}]\)拆开变成:

\[\dfrac{i-i\%k}{k}\]

于是原问题变成:

\[\sum_{i=0}^n\dbinom{n}{i}*p^i*\dfrac{i-i\%k}{k}\]

看到了\(i\%k\),然后还有组合数,然后\(k\)还是\(2\)的整数次幂,这个时候当然是单位根反演上场了...

\[\sum_{t=0}^{k-1}\sum_{i=0}^n[i\%k==t]\dbinom{n}{i}*\dfrac{i-t}{k}*p^i\]

然后就是喜闻乐见的化式子了

\[\sum_{t=0}^{k-1}\sum_{i=0}^n[(i-t)\%k==0]\dbinom{n}{i}*\dfrac{i-t}{k}p^i\]

\[\sum_{t=0}^{k-1}\sum_{i=0}^n\dfrac{1}{k}\sum_{j=0}^{k-1}\omega_{k}^{(i-t)j} *\dbinom{n}{i}*\dfrac{i-t}{k}p^i\]

\[\dfrac{1}{k^2}\sum_{t=0}^{k-1}\sum_{i=0}^n\sum_{j=0}^{k-1}\omega_{k}^{(i-t)j} *\dbinom{n}{i}*(i-t)p^i\]

\[\dfrac{1}{k^2}\sum_{t=0}^{k-1}\sum_{i=0}^n\sum_{j=0}^{k-1}\omega_{k}^{ij}*\omega_{k}^{-tj} *\dbinom{n}{i}*(i-t)p^i\]

然后肯定要交换求和顺序变成:

\[\dfrac{1}{k^2}\sum_{t=0}^{k-1}\sum_{j=0}^{k-1}\omega_{k}^{-tj}\sum_{i=0}^{n}\omega_{k}^{ij} *\dbinom{n}{i}*(i-t)p^i\]

然后这里是可以将其拆开的...

\[\dfrac{1}{k^2}\sum_{t=0}^{k-1}\sum_{j=0}^{k-1}\omega_{k}^{-tj}\sum_{i=0}^{n}\omega_{k}^{ij} *\dbinom{n}{i}*i*p^i-\dfrac{1}{k^2}\sum_{t=0}^{k-1}\sum_{j=0}^{k-1}\omega_{k}^{-tj}\sum_{i=0}^{n}\omega_{k}^{ij} *\dbinom{n}{i}*tp^i\]

我们先忽略\(\dfrac{1}{k^2}\)

\[\sum_{t=0}^{k-1}\sum_{j=0}^{k-1}\omega_{k}^{-tj}\sum_{i=0}^{n}\omega_{k}^{ij} *\dbinom{n}{i}*i*p^i-\sum_{t=0}^{k-1}t*\sum_{j=0}^{k-1}\omega_{k}^{-tj}\sum_{i=0}^{n}\omega_{k}^{ij} *\dbinom{n}{i}p^i\]

\[\sum_{t=0}^{k-1}\sum_{j=0}^{k-1}\omega_{k}^{-tj}\sum_{i=0}^{n}(\omega_{k}^{j}p)^i *\dbinom{n}{i}*i-\sum_{t=0}^{k-1}t*\sum_{j=0}^{k-1}\omega_{k}^{-tj}\sum_{i=0}^{n}(\omega_{k}^{j}p)^i *\dbinom{n}{i}\]

第二个式子很好处理,我们直接用二项式定理即可化开变成:

\[\sum_{t=0}^{k-1}t*\sum_{j=0}^{k-1}\omega_{k}^{-tj}(\omega_{k}^{j}p+1)^n\]

然后对于某一个\(j\)\((\omega_{k}^{j}p+1)^n\)为定值,设其为\(a_j\)

第一个式子可以将组合数拆开

\[\sum_{t=0}^{k-1}\sum_{j=0}^{k-1}\omega_{k}^{-tj}\sum_{i=0}^{n}(\omega_{k}^{j}p)^i *\dbinom{n}{i}*i\]

\[\sum_{t=0}^{k-1}\sum_{j=0}^{k-1}\omega_{k}^{-tj}\sum_{i=0}^{n}(\omega_{k}^{j}p)^i *\dfrac{n!}{i!*(n-i)!}*i\]

然后这个时候可以将\(i=0\)的那一项给忽略掉

\[\sum_{t=0}^{k-1}\sum_{j=0}^{k-1}\omega_{k}^{-tj}\sum_{i=1}^{n}(\omega_{k}^{j}p)^i *\dfrac{n!}{(i-1)!(n-i)!}\]

\[\sum_{t=0}^{k-1}\sum_{j=0}^{k-1}\omega_{k}^{-tj}\sum_{i=1}^{n}(\omega_{k}^{j}p)^i *\dfrac{n*(n-1)!}{(i-1)!((n-1)-(i-1))!}\]

\[n*\sum_{t=0}^{k-1}\sum_{j=0}^{k-1}\omega_{k}^{-tj}\sum_{i=1}^{n}(\omega_{k}^{j}p)^{i-1+1}*\dfrac{(n-1)!}{(i-1)!((n-1)-(i-1))!}\]

\[n*\sum_{t=0}^{k-1}\sum_{j=0}^{k-1}\omega_{k}^{-tj}\sum_{i=1}^{n}(\omega_{k}^{j}p)^{i-1}*\omega_{k}^jp*\dfrac{(n-1)!}{(i-1)!((n-1)-(i-1))!}\]

\[n*\sum_{t=0}^{k-1}\sum_{j=0}^{k-1}\omega_{k}^{-tj}*\omega_{k}^jp\sum_{i-1=0}^{n-1}(\omega_{k}^{j}p)^{i-1}*\dfrac{(n-1)!}{(i-1)!((n-1)-(i-1))!}\]

\[n*\sum_{t=0}^{k-1}\sum_{j=0}^{k-1}\omega_{k}^{-tj}*\omega_{k}^jp\sum_{i-1=0}^{n-1}(\omega_{k}^{j}p)^{i-1}* \dbinom{i-1}{n-1}\]

\[n*\sum_{t=0}^{k-1}\sum_{j=0}^{k-1}\omega_{k}^{-tj}*\omega_{k}^jp\sum_{i=0}^{n-1}(\omega_{k}^{j}p)^{i}* \dbinom{i}{n-1}\]

\[n*\sum_{t=0}^{k-1}\sum_{j=0}^{k-1}\omega_{k}^{-tj}*\omega_{k}^jp*(\omega_{k}^{j}p+1)^{n-1}\]

后面那一坨对于某一个\(j\)也是固定的,我们可以设\(b_j=\omega_{k}^jp*(\omega_{k}^jp+1)^{n-1}\)

那么就有原式即:

\[n*\sum_{t=0}^{k-1}\sum_{j=0}^{k-1}\omega_{k}^{-tj}*b_j-\sum_{t=0}^{k-1}t*\sum_{j=0}^{k-1}\omega_{k}^{-tj}a_j\]

然后我们就得到了一个\(O(k^2)\)的做法了...

然后我们用一下白兔之舞的神仙操作\(tj=\dfrac{(t+j)(t+j-1)}{2}-\dfrac{j(j-1)}{2}-\dfrac{t(t-1)}{2}\)

证明也很简单,分子是:

\[(t+j)^2-t-j-j^2+j-t^2+t\]

\[2tj\]

所以原式就可以化成:

\[n*\sum_{t=0}^{k-1}\sum_{j=0}^{k-1}\omega_{k}^{-(\binom{2}{t+k}-\binom{2}{t}-\binom{2}{j})}*b_j-\sum_{t=0}^{k-1}t*\sum_{j=0}^{k-1}\omega_{k}^{-(\binom{2}{t+k}-\binom{2}{t}-\binom{2}{j})}a_j\]

\[n*\sum_{t=0}^{k-1}\sum_{j=0}^{k-1}\omega_{k}^{-\binom{2}{t+k}+\binom{2}{t}+\binom{2}{j}}*b_j-\sum_{t=0}^{k-1}t*\sum_{j=0}^{k-1}\omega_{k}^{-\binom{2}{t+k}+\binom{2}{t}+\binom{2}{j}}a_j\]

\[n*\sum_{t=0}^{k-1}\sum_{j=0}^{k-1}\omega_{k}^{-\binom{2}{t+k}} \omega_{k}^{\binom{2}{t}}\omega_k^{\binom{2}{j}}*b_j-\sum_{t=0}^{k-1}\sum_{j=0}^{k-1}\omega_{k}^{-\binom{2}{t+k}} t*\omega_{k}^{\binom{2}{t}}\omega_k^{\binom{2}{j}}a_j\]

然后如果我们将\(t+k\)看作一个整体那么就会发现这是一个卷积的形式

然后就只需要将\(\omega_{k}^{\binom{j}{t}}\)\(\omega_k^{\binom{2}{j}}*b_j\)以及\(t*\omega_{k}^{\binom{j}{t}}\)\(\omega_k^{\binom{2}{j}}*a_j\)分别卷起来即可,暴力卷是需要\(\rm 6NTT\)的...

还担心会\(\rm T\)来着...然而事实上也不慢,开\(\rm O2\)最慢的点才\(1.3s\)..不过其实可以做\(\rm 3FFT\)的...因为卷起来可以将结果乘起来再加起来...同时把两个多项式的\(\rm DFT\)算出来需要\(3\)次变\(2\)次的技巧...所以速度应该会还可以

复杂度\(O(k\log k)\)

\(Code:\)

#include<bits/stdc++.h>
using namespace std ;
#define rep( i, s, t ) for( register int i = s; i <= t; ++ i )
#define re register
#define LL long long
#define int long long
int gi() {
    char cc = getchar() ; int cn = 0, flus = 1 ;
    while( cc < '0' || cc > '9' ) {  if( cc == '-' ) flus = - flus ; cc = getchar() ; }
    while( cc >= '0' && cc <= '9' )  cn = cn * 10 + cc - '0', cc = getchar() ;
    return cn * flus ;
}
const int Gi = 332748118 ;
const int P = 998244353 ; 
const int N = 4e6 + 5 ;  
const int G = 3 ;
int n, p, m, limit, L, R[N] ;
LL A[N], B[N], F[N], F2[N], Dg[N], Inv ;
LL fpow( LL x, int k ) {
    LL ans = 1, base = x % P ; k = k % ( P - 1 ) ; 
    while( k ) {
        if( k & 1 ) ans = ( ans * base ) % P ; 
        base = ( base * base ) % P, k >>= 1 ; 
    }
    return ans % P ;
}
void NTT( LL *a, int type ) {
    for( re int i = 0; i < limit; ++ i ) if( i < R[i] ) swap( a[i], a[R[i]] ) ;
    for( re int k = 1; k < limit; k <<= 1 ) {
        LL dg = fpow( ( type == 1 ) ? G : Gi, ( P - 1 ) / ( k << 1 ) ); 
        for( re int i = 0; i < limit; i += ( k << 1 ) )
        for( re LL j = i, g = 1; j < i + k; ++ j, g = ( g * dg ) % P ) {
            LL Nx = a[j], Ny = ( a[j + k] * g ) % P;
            a[j] = ( Nx + Ny ) % P, a[j + k] = ( Nx - Ny + P ) % P ; 
        }
    }
    if( type != 1 ) rep( i, 0, limit - 1 ) a[i] = ( a[i] * Inv ) % P ; 
}
void Init() {
    limit = 1, L = 0 ;
    while( limit < m + m ) limit <<= 1, ++ L ; 
    for( int i = 0; i < limit; ++ i ) R[i] = ( R[i >> 1] >> 1 ) | ( ( i & 1 ) << ( L - 1 ) ) ;
    Inv = fpow( limit, P - 2 ) ;
}
LL C( int x ) {
    return 1ll * x * ( x - 1 ) / 2 ; 
}
signed main()
{
    n = gi(), p = gi(), m = gi() ;  
    Dg[0] = 1, Dg[1] = fpow( G, ( P - 1 ) / m ) ;
    rep( i, 2, m ) Dg[i] = ( Dg[i - 1] * Dg[1] ) % P ; 
    rep( i, 0, m - 1 ) A[i] = fpow( Dg[i] * p + 1, n ), B[i] = Dg[i] * p % P * fpow( Dg[i] * p + 1, n - 1 ) % P ;
    
    LL Ans1 = 0, Ans2 = 0, Ans = 0 ;
    rep( i, 0, m - 1 ) A[i] = Dg[C(i) % m] * A[i] % P, B[i] = Dg[C(i) % m] * B[i] % P, 
    F[i] = Dg[C(i) % m] % P, F2[i] = 1ll * i * Dg[C(i) % m] % P ;
    Init(), NTT( A, 1 ), NTT( B, 1 ), NTT( F, 1 ), NTT( F2, 1 ) ; 
    rep( i, 0, limit - 1 ) A[i] = ( F2[i] * A[i] ) % P, B[i] = ( F[i] * B[i] ) % P ;
    NTT( A, -1 ), NTT( B, -1 ) ;
    
    rep( i, 0, limit ) A[i] = A[i] * Dg[m - C(i) % m] % P, B[i] = B[i] * Dg[m - C(i) % m] % P, 
        Ans2 = ( Ans2 + A[i] ) % P, Ans1 = ( Ans1 + B[i] ) % P ; 
    
    Ans1 = ( 1ll * Ans1 * ( n % P ) ) % P ;  
    Ans = ( Ans1 - Ans2 + P ) % P ;
    Ans = ( Ans * fpow( m * m % P, P - 2 ) ) % P ;
    printf("%lld\n", Ans ) ;
    return 0 ;
}

因为多项式实在是做少了所以调得非常自闭...,下次再写我开数组绝对不这么吝啬QAQ我错了

luoguP5591 【小猪佩奇学数学】

原文:https://www.cnblogs.com/Soulist/p/11673254.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!