[tyvj1858]XLKxc

题目

点这里看题目。

题目简述:

给定(k,a,n,d),满足(kle 123, a,n,dle 123456789),求:

[sum_{t=0}^nsum_{j=1}^{a+td}sum_{i=1}^ji^k ]

答案对(1234567891)(不用看了,是个质数)取模。

分析

一个神奇的......插值套插值套插值的题目。

首先,发现(f(n))可以直接插值求出来,是关于(n)(k+1)次多项式。

然后,差分一下(g),发现(g(n))也可以直接插值求出来,是关于(n)(k+2)次多项式。

最后,差分一下(h),发现(h(n))还可以直接插值求出来,是关于(n)(k+3)次多项式。((h(n)-h(n-1)=g(a+nd))(g)(k+2)次的)

然后,用(O(k^2))的时间处理(h)的前(k+4)个点的值,再用(O(k))时间插值就好。

数据好像有问题,dark上面有一组数据超过范围了

代码

#include<cstdio>

typedef long long LL;

#define int LL

const int mod = 1234567891;
const int MAXK = 205;

template<typename _T>
void read( _T &x )
{
	x = 0;char s = getchar();int f = 1;
	while( s > '9' || s < '0' ){if( s == '-' ) f = -1; s = getchar();}
	while( s >= '0' && s <= '9' ){x = ( x << 3 ) + ( x << 1 ) + ( s - '0' ), s = getchar();}
	x *= f;
}

template<typename _T>
void write( _T x )
{
	if( x < 0 ){ putchar( '-' ); x = ( ~ x ) + 1; }
	if( 9 < x ){ write( x / 10 ); }
	putchar( x % 10 + '0' );
}

LL pk[MAXK], S[MAXK], SPre[MAXK], H[MAXK];
LL K, A, N, D;

LL qkpow( LL base, LL indx )
{
	LL ret = 1;
	while( indx )
	{
		if( indx & 1 ) ret = ret * base % mod;
		base = base * base % mod, indx >>= 1;
	}
	return ret;
}

LL ID( const LL i ) { return A + D * i; }
LL inv( const LL a ) { return qkpow( a % mod, mod - 2 ); }
LL fix( const LL a ) { return ( a % mod + mod ) % mod; }
void add( LL &x, const LL v ) { x = ( x + v >= mod ? x + v - mod : x + v ); }

LL Lagrange( LL n, const LL M, LL *B )
{
	if( n <= M ) return B[n]; n %= mod;
	LL ans = 0, w = 1, L = 1;
	for( int i = 1 ; i <= M ; i ++ ) L = L * ( n - i ) % mod;
	for( int i = 2 ; i <= M ; i ++ ) w = w * inv( fix( 1 - i ) ) % mod;
	for( int i = 1 ; i <= M ; i ++ )
	{
		add( ans, L * w % mod * inv( n - i ) % mod * B[i] % mod );
		if( i < M ) w = w * fix( i - M ) % mod * inv( i ) % mod;
	}
	return ans;
}

LL f( const LL n ) { return Lagrange( n, K + 2, S ); }      //k+1
LL g( const LL n ) { return Lagrange( n, K + 3, SPre ); }   //k+2
LL h( const LL n ) { return Lagrange( n, K + 4, H ); }      //k+3

void init()
{
	for( int i = 1 ; i <= K + 5 ; i ++ ) pk[i] = qkpow( i, K );
	for( int i = 1 ; i <= K + 5 ; i ++ ) S[i] = ( S[i - 1] + pk[i] ) % mod;
	for( int i = 1 ; i <= K + 5 ; i ++ ) SPre[i] = ( SPre[i - 1] + S[i] ) % mod;
	for( int i = 1 ; i <= K + 5 ; i ++ ) H[i] = ( H[i - 1] + g( ID( i - 1 ) ) ) % mod;
}

signed main()
{
	int T;
	read( T );
	while( T -- )
	{
		read( K ), read( A ), read( N ), read( D );
		init(); 
		write( h( N + 1 ) ), putchar( '
' );
	}
	return 0;
}
原文地址:https://www.cnblogs.com/crashed/p/13130775.html