题解 P4464 【[国家集训队]JZPKIL】
多次查询,每次给定
-
T\le 100,1\le n\le 10^{18},x,y\le 3000
答案是:
枚举
我们将
注意到后者可以视为
设结果为
-
\Z(1)=1 -
\Z(p)=p^x+p^c-p^y -
\Z(p^k)=f\cdot h^c(p^k)-f\cdot h^c(p^{k-1})\times p^y
于是只需要考虑
所以通过 MR 进行暴力质因数分解,然后我们
还有一个问题,如何计算自然数幂的和的多项式?
自然数幂和多项式
构造多项式
将
所以我们会发现其实有
换而言之如果能够得到伯努利数那么就可以知道自然数幂和多项式
然后只需要递推伯努利数即可。
注意到
所以有:
于是得到
综上,本题复杂度为
然后这道题卡常,你需要尽可能的省略快速幂,如果你是
然后千万不要写龟速乘,然后挑一个夜深人静的时候交一发,多洗一下脸,没准就过了。
不过我在 darkbzoj 这道题过得非常稳...但是咕咕就死得非常惨
#include<bits/stdc++.h>
using namespace std ;
#define Next( i, x ) for( register int i = head[x]; i; i = e[i].next )
#define rep( i, s, t ) for( register int i = (s); i <= (t); ++ i )
#define drep( i, s, t ) for( register int i = (t); i >= (s); -- i )
#define re register
#define int __int128
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 M = 3000 + 5 ;
const int P = 1e9 + 7 ;
int n, fx, fy, fc, maxn, top, cnt, num, tp[M], st[M], w[M], fac[M], inv[M], B[M], f[M] ;
int mul( int a, int b, int p ) {
return a * b % p ;
}
int fpow( int x, int k, int p ) {
int ans = 1, base = x ;
while(k) {
if(k & 1) ans = mul(ans, base, p) ;
base = mul(base, base, p), k >>= 1 ;
} return ans ;
}
int sw( int x ) { return ( ( 1ll * rand() << 16ll ) | rand() ) % x + 1 ; }
bool M_R( int p ) {
if( p == 2 || p == 3 ) return 1 ;
if( p == 1 || ( p % 2 == 0 ) ) return 0 ;
re int d = p - 1, s = 0 ; while( !( d & 1 ) ) ++ s, d >>= 1 ;
rep( i, 0, 5 ) {
re int a = sw( p - 3 ) + 2 ;
re int x = fpow( a, d, p ), y = 0 ;
for( register int j = 0; j < s; ++ j ) {
y = mul( x, x, p ) ; if( y == 1 && ( x != 1 ) && x != ( p - 1 ) ) return 0 ;
x = y ;
} if( y != 1 ) return 0 ;
} return 1 ;
}
int gcd( int x, int y ) {
return ( x == 0 ) ? y : gcd( y % x, x ) ;
}
int work( int p ) {
re int k = 2, x = sw(p - 1), y = x, d = 1, c = sw(99997) ;
for( re int i = 1; d == 1; ++ i ) {
x = ( mul( x, x, p ) + c ) % p ;
d = gcd( (x > y) ? x - y : y - x, p ) ;
if( i == k ) y = x, k <<= 1 ;
} return d ;
}
void Pollard_Rho(int p) {
if( p == 1 ) return ;
if( M_R(p) ) { st[++ top] = p; return ; }
int x = p ; while( x == p ) x = work(x) ;
Pollard_Rho(x), Pollard_Rho(p / x) ;
}
int g[M], gg[M], fg[M], fgg[M], fff[M] ;
int c( int x, int y ) {
if( x < y ) return 0 ;
return fac[x] * inv[y] % P * inv[x - y] % P ;
}
signed main()
{
srand(time(NULL)) ;
int T = gi() ; maxn = 3002 ; B[0] = 1, fac[0] = inv[0] = 1 ;
rep( i, 1, maxn ) fac[i] = fac[i - 1] * i % P, inv[i] = fpow( fac[i], P - 2, P ) ;
rep( i, 1, maxn ) {
for( re int j = 0; j < i; ++ j ) B[i] = ( B[i] - c(i + 1, j) * B[j] % P + P ) % P ;
B[i] = B[i] * fpow( i + 1, P - 2, P ) % P, ++ B[i] ;
}
while( T-- ) {
n = gi(), fx = gi(), fy = gi() ; int k = fy ; top = 0 ;
for( re int i = 0; i <= k; ++ i ) f[k - i + 1] = B[i] * c(k + 1, i) % P * fpow( k + 1, P - 2, P ) % P ;
Pollard_Rho(n), sort(st + 1, st + top + 1) ; cnt = 0 ;
rep( i, 1, top ) {
if( st[i] != st[i - 1] ) tp[++ cnt] = st[i] ;
++ w[cnt] ;
} int Ans = 0 ;
rep( j, 1, cnt ) fg[j] = fpow( tp[j], fx, P ), fff[j] = fpow(tp[j], fy, P) ;
for( re int ic = 0; ic <= k + 1; ++ ic ) {
int ans = 1 ;
for( re int j = 1; j <= cnt; ++ j ) {
int tk = w[j], qwq = 0, de = 0 ;
g[0] = 1, gg[0] = 1 ; fgg[j] = ( !ic ) ? 1 : fgg[j] * tp[j] % P ;
int dg = fg[j], dgg = fgg[j] ;
for( re int o = 1; o <= w[j]; ++ o )
g[o] = g[o - 1] * dg % P, gg[o] = gg[o - 1] * dgg % P ;
for( re int o = 0; o <= w[j]; ++ o )
qwq = ( qwq + g[o] * gg[(w[j] - o)] % P ) % P ;
for( re int o = 0; o < w[j]; ++ o )
de = ( de + g[o] * gg[(w[j] - o - 1)] % P ) % P ;
ans = ans * ( qwq - de * fff[j] % P + P ) % P ;
}
Ans = ( Ans + ans * f[ic] % P + P ) % P ;
} rep( i, 1, cnt ) w[i] = tp[i] = 0 ;
cout << (long long)(Ans * fpow( n, fy, P ) % P) << endl ;
}
return 0 ;
}