P4464 [国家集训队]JZPKIL

如果不知道伯努利数的点这里

\[\sum_{i=1}^n (i,n)^x[i,n]^y \]

\[\sum_{i=1}^n (i,n)^{x-y} \times i^y \times n^y \]

\[n^y \sum_{d|n} d ^{x-y} \sum_{i=1}^n [(i,n)=d] i^y \]

\[n^y \sum_{d|n} d ^{x} \sum_{i=1}^{\lfloor \frac{n}{d} \rfloor} [(i,\frac{n}{d})=1] i^y \]

\[n^y \sum_{d|n} d ^{x} \sum_{i=1}^{\lfloor \frac{n}{d} \rfloor} \sum_{s|(i,\frac{n}{d})}\mu(s)i^y \]

\[n^y \sum_{d|n} d ^{x} \sum_{s|\frac{n}{d}} \mu(s) \sum_{i=1}^{\frac{n}{ds}}(is)^y \]

\[n^y \sum_{d|n} d ^{x} \sum_{s|\frac{n}{d}} \mu(s) s^y \sum_{i=1}^{\frac{n}{ds}}i^y \]

\(k_i\)\(y\) 次幂展开后 \(n^i\) 的系数

\[n^y \sum_{d|n} d ^{x} \sum_{s|\frac{n}{d}} \mu(s) s^y \sum_{i=1}^{y+1} k_i (\frac{n}{ds})^i \]

\[n^y \sum_{i=1}^{y+1} k_i\sum_{d|n} d ^{x} \sum_{s|\frac{n}{d}} \mu(s) s^y (\frac{n}{ds})^i \]

后面是卷积的形式,记为 \(f(i)\)

\(f_1(n)=n^x,f_2(n)=\mu(n)n^y,f_3(n)=n^i\)

那么 \(f=f_1*f_2*f_3\) ,也为一个积性函数,考虑求出 \(f(p^w)\)

\(s\) 只有等于 \(1\)\(p\)\(\mu(s)\not=0\),

\(s = 1\)

\[f(n)=\sum_{d|n} d ^{x} \sum_{s|\frac{n}{d}} \mu(s) s^y (\frac{n}{ds})^i \]

\[=n^i\sum_{d|n} d ^{x-i} \]

\[f(p^k)=p^{ki}\sum_{d|p^k}d^{x-i} \]

\[=p^{ki}\sum_{j=0}^k p^{j(x-i)} \]

\(s=p\)

\[f(n)=\sum_{d|n} d ^{x} \sum_{s|\frac{n}{d}} \mu(s) s^y (\frac{n}{ds})^i \]

\[=\sum_{d|n} d ^{x} \mu(p) p^y (\frac{n}{dp})^i \]

\[=-n^i\sum_{d|n} d ^{x-i} p ^{y-i} \]

\[f(p^k)=-p^{ki}\sum_{d|p^k}d^{x-i}p ^{y-i} \]

\[=-p^{ki}\sum_{j=0}^{k-1} p^{j(x-i)}p ^{y-i} \]

\[=-p^{ki+y-i}\sum_{j=0}^{k-1} p^{j(x-i)} \]

然后用 \(\text{Pollard~rho}\) 分解质因数后计算。

但计算等比数列和时不能用公式算,也不能暴力算(具体看代码注释)。

这份常数极大的代码不开o2会t。

#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
using namespace std;
#define Lint __int128
#define LL long long

template<typename _T>
void Read( _T &x ) {
	x = 0; int f = 1;
	char s = getchar( );
	for( ; s < '0' || s > '9' ; s = getchar( ) ) f = s == '-' ? -f : f;
	for( ; s >= '0' && s <= '9' ; s = getchar( ) ) x = x * 10 + s - '0';
	x *= f;
}
template<typename _T>
void Write( _T x ) {
	if( x < 0 ) putchar( '-' ) , x = -x;
	if( x >= 10 ) Write( x / 10 );
	putchar( x % 10 + '0' );
}

const int MAXN = 3005 , Mod = 1e9 + 7;
LL n;
int t , x , y;

template<typename _T>
_T Quick_pow( _T x , _T po , _T p = Mod ) {
	_T Ans = 1; bool f = 0;
    if( po < 0 ) po = -po , f = 1;
	while( po ) {
		if( po % 2 )
			Ans = (Lint)Ans * x % p;
		x = (Lint)x * x % p;
		po /= 2;
	}
	return f ? Quick_pow( (int)Ans , Mod - 2 ) : Ans;
}
template<typename _T>
_T Gcd( _T x , _T y ) {
	return y == 0 ? x : Gcd( y , x % y );
}
template<typename _T>
_T Abs( _T x ) {
	return x >= 0 ? x : -x;
}
template<typename _T>
_T Inverse( _T x ) {
    return Quick_pow( x , Mod - 2 );
}

template<typename _T>
_T f( _T x , _T a , _T Mod ) {
	return ( (Lint)x * x + a ) % Mod;
}
LL Pollard_rho( LL n ) {
	LL r = rand( ) % ( n - 1 ) + 1;
	LL s = 0 , t = 0 , val , d;
	for( int k = 1 ; k ; k <<= 1 ) {
		val = 1; s = t;
		for( int i = 1 ; i <= k ; i ++ ) {
			t = f( t , r , n );
			val = (Lint)val * Abs( t - s ) % n;
			if( i % 127 == 0 && ( d = Gcd( val , n ) ) > 1 ) return d;
		}
		if( ( d = Gcd( val , n ) ) > 1 ) return d;
	}
}

int prinum = 12;
LL prime[ 20 ] = { 0 , 2 , 3 , 5 , 7 , 11 , 13 , 17 , 19 , 23 , 29 , 31 , 37 };
bool Miller_Rabin( LL x ) {
	if( x == 0 || x == 1 ) return 0;
	for( int i = 1 ; i <= prinum ; i ++ ) {
		if( x == prime[ i ] ) return 1;
		if( x < prime[ i ]  ) return 0;
		
		LL s = Quick_pow( prime[ i ] , x - 1 , x ) , tmp = x - 1;
		if( s != 1 ) return 0; 
		while( s == 1 && tmp % 2 == 0 ) {
			tmp /= 2;
			s = Quick_pow( prime[ i ] , tmp , x );
			if( s != 1 && s != x - 1 ) return 0;
		}
	}
	return 1;
}

int k; LL pi[ 100 ];
void Divide( LL x ) {
	if( x == 1 ) return;
	if( Miller_Rabin( x ) ) {
		pi[ ++ k ] = x; return;
	}
	if( x == 4 ) {
		pi[ ++ k ] = 2 , pi[ ++ k ] = 2;
		return;
	}
	LL p = x;
	while( p == x ) p = Pollard_rho( x );
	Divide( p ) , Divide( x / p );
} 

int Fac[ MAXN + 5 ] , Inv[ MAXN + 5 ];
void Init_Fac( ) {
    Fac[ 0 ] = 1;
    for( int i = 1 ; i <= MAXN ; i ++ ) Fac[ i ] = 1ll * Fac[ i - 1 ] * i % Mod;
    Inv[ MAXN ] = Inverse( Fac[ MAXN ] );
    for( int i = MAXN ; i >= 1 ; i -- ) Inv[ i - 1 ] = 1ll * Inv[ i ] * i % Mod;
}
int C( int n , int m ) {
    return 1ll * Fac[ n ] * Inv[ m ] % Mod * Inv[ n - m ] % Mod;
}

int Bernoulli[ MAXN + 5 ] , S[ MAXN + 5 ];
void Init_Bernoulli( ) {
    Bernoulli[ 0 ] = 1;
    for( int i = 1 ; i <= MAXN ; i ++ ) {
        int Sum = 0;
        for( int j = 0 ; j < i ; j ++ )
            Sum = ( Sum + 1ll * C( i + 1 , j ) * Bernoulli[ j ] % Mod ) % Mod;
        Bernoulli[ i ] = ( -1ll * Sum * Inverse( C( i + 1 , i ) ) % Mod + Mod ) % Mod;
    }Bernoulli[ 1 ] ++;
}

LL di[ MAXN + 5 ];
int wi[ MAXN + 5 ];

/*int Aq( int a , int q , int n ) {
    if( q == 1 ) return 1ll * a * n % Mod;
    return 1ll * a * ( 1 - Quick_pow( q , n ) + Mod ) % Mod * Inverse( 1 - q ) % Mod;
}*/
int F( int p , int w , int i ) {
//	int Ans = 0;
//	for( int j = 0 ; j <= w ; j ++ ) Ans = ( Ans + Quick_pow( p , w * i + j * ( x - i ) ) ) % Mod;
//	for( int j = 0 ; j <  w ; j ++ ) Ans = ( Ans - Quick_pow( p , w * i + y - i + j * ( x - i ) ) ) % Mod;
//	return ( Ans + Mod ) % Mod;

//	return ( ( Aq( Quick_pow( p , w * i ) , Quick_pow( p , x - i ) , w + 1 ) - Aq( Quick_pow( p , w * i + y - i ) , Quick_pow( p , x - i ) , w ) ) % Mod + Mod ) % Mod;

	int Ans = 0 , a , q = Quick_pow( p , x - i );
	a = Quick_pow( p , w * i );
	for( int j = 0 ; j <= w ; j ++ ) Ans = ( Ans + a ) % Mod , a = 1ll * a * q % Mod; 
	a = Quick_pow( p , w * i + y - i );
	for( int j = 0 ; j <  w ; j ++ ) Ans = ( Ans - a ) % Mod , a = 1ll * a * q % Mod; 
	return ( Ans + Mod ) % Mod;
}

/*
p^{wi}*p^{j(x-i)}
a1:p^{wi} q:p^(x-i) n:w+1

p^{wi+y-i}*p^{j(x-i)}
a1:p^{wi+y-i} q:p^(x-i) n:w
*/

int Solve( LL n , int x , int y ) {
	if( n == 0 ) return 0;
	k = 0; Divide( n );
	sort( pi + 1 , pi + k + 1 );
	
	S[ 0 ] = 0;
	for( int i = 0 ; i <= y ; i ++ )
		S[ y + 1 - i ] = 1ll * Inverse( y + 1 ) * C( y + 1 , i ) % Mod * Bernoulli[ i ] % Mod;

	int cnt = 0;
	for( int i = 1 ; i <= k ; i ++ ) {
		if( pi[ i ] != di[ cnt ] ) di[ ++ cnt ] = pi[ i ] , wi[ cnt ] = 1;
		else wi[ cnt ] ++;
	}

	int Ans = 0;
	for( int i = 0 ; i <= y + 1 ; i ++ ) {
		int tmp = 1;
		for( int j = 1 ; j <= cnt ; j ++ )
			tmp = 1ll * tmp * F( (int)( di[ j ] % Mod ) , wi[ j ] , i ) % Mod;
        Ans = ( Ans + 1ll * S[ i ] * tmp % Mod ) % Mod;
	}
	return 1ll * Quick_pow( int( n % Mod ) , y ) * Ans % Mod;
}

signed main() {
    srand( time( 0 ) );
    Init_Fac( );
    Init_Bernoulli( );

	Read( t );
    while( t -- ) {
        Read( n ) , Read( x ) , Read( y );
		Write( Solve( n , x , y ) ) , putchar('\n');
    }
    return 0;
}

------------恢复内容结束------------

posted @ 2021-04-08 20:43  chihik  阅读(51)  评论(0编辑  收藏  举报