luoguP5591 【小猪佩奇学数学】

由于存在一道题叫做白兔之舞就导致这道题看上去非常的板\(......(\)如果按照这个方法推下来

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

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

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

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

于是原问题变成:

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

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

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

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

\[\sum_{t=0}^{k-1}\sum_{i=0}^n[(i-t)\%k==0]\dbinom{n}{i}\times \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} \times\dbinom{n}{i} \times\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} \times\dbinom{n}{i}\times(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}\times\omega_{k}^{-tj} \times\dbinom{n}{i}\times(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} \times \dbinom{n}{i}\times (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} \times \dbinom{n}{i}\times i\times 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} \times \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} \times \dbinom{n}{i}\times i\times p^i-\sum_{t=0}^{k-1}t\times \sum_{j=0}^{k-1}\omega_{k}^{-tj}\sum_{i=0}^{n}\omega_{k}^{ij} \times \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 \times \dbinom{n}{i}\times i-\sum_{t=0}^{k-1}t\times \sum_{j=0}^{k-1}\omega_{k}^{-tj}\sum_{i=0}^{n}(\omega_{k}^{j}p)^i \times \dbinom{n}{i} \]

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

\[\sum_{t=0}^{k-1}t\times \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 \times \dbinom{n}{i}\times i \]

\[\sum_{t=0}^{k-1}\sum_{j=0}^{k-1}\omega_{k}^{-tj}\sum_{i=0}^{n}(\omega_{k}^{j}p)^i \times \dfrac{n!}{i!*(n-i)!}\times 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 \times \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 \times \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}\times \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\times \dfrac{(n-1)!}{(i-1)!((n-1)-(i-1))!} \]

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

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

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

\[n*\sum_{t=0}^{k-1}\sum_{j=0}^{k-1}\omega_{k}^{-tj}\times \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}\times 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 \]

所以原式就可以化成:

下面的组合数都反了,但我懒得改了QAQ

\[n*\sum_{t=0}^{k-1}\sum_{j=0}^{k-1}\omega_{k}^{-(\binom{2}{t+k}-\binom{2}{t}-\binom{2}{j})}\times 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}}\times b_j-\sum_{t=0}^{k-1}t\times \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\times \omega_{k}^{\binom{2}{t}}\omega_k^{\binom{2}{j}}a_j \]

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

然后就只需要将\(\omega_{k}^{\binom{2}{t}}\)\(\omega_k^{\binom{2}{j}}\times b_j\)以及\(t\times \omega_{k}^{\binom{2}{t}}\)\(\omega_k^{\binom{2}{j}}\times 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我错了

posted @ 2019-10-14 19:11  Soulist  阅读(179)  评论(0编辑  收藏  举报