#include #include #include #include #include #define REP(i,a,b) for(i=a;i0){ q=r0/r1; r2=r0%r1; a2=a0-q*a1; b2=b0-q*b1; r0=r1; r1=r2; a0=a1; a1=a2; b0=b1; b1=b2; } *c=r0; *a=a0; *b=b0; } /* n^(-1) mod p */ ll get_inv(ll n, ll p){ ll a,b,c; extended_euclid(n,p,&c,&a,&b); if(a>32; if(xh) res -= 32, xl = xh; if(xl&0xffff0000U) res -= 16, xl >>= 16; if(xl&0x0000ff00U) res -= 8, xl >>= 8; return res + ullNumberOfLeadingZerosTable[xl]; } /* (x*y)%m (x,y < m) */ ull ullMultipleMod(ull x, ull y, ull m){ int k,loop=2; ull xlo,xhi,ylo,yhi,rlo,rhi,d1,d2,a,q,r,mask=0xffffffffULL; assert(x < m && y < m); if(m<=mask) return (x*y)%m; xlo=(x&mask); xhi=(x>>32); ylo=(y&mask); yhi=(y>>32); rhi=xhi*yhi; rlo=xlo*ylo; a=(rlo>>32)+xhi*ylo; rhi+=(a>>32); a&=mask; a+=xlo*yhi; rhi+=(a>>32); rlo = (rlo&mask) | ((a&mask)<<32); k = ullNumberOfLeadingZeros(m); rhi = (rhi<>(64-k)); rlo<<=k; m<<=k; d1=(m>>32); d2=(m&mask); while(loop--){ r = rhi/d1*d2; rhi = ( (rhi%d1 << 32) | (rlo>>32) ); rlo = ( (rlo&mask) << 32 ); if(rhim) rhi+=m; } return rhi>>k; } /* (x^k)%m */ ull ullPowMod(ull x, ull k, ull m){ ull res; if(k==0) return 1; res = ullPowMod(x,k/2,m); res = ullMultipleMod(res,res,m); if(k%2) res = ullMultipleMod(res,x,m); return res; } /* prod mod[k] < 2^62*/ /* GCD(mod[i],mod[j]) = 1 */ ll llChineseRemainderTheorem(ll val[], ll mod[], int sz){ int i, j; ll m1, m2, m; ll a, b, c, res = 0; if(sz==1) return val[0]; m = 1; rep(i,sz) m *= mod[i]; rep(i,sz){ m1 = mod[i]; m2 = m / m1; extended_euclid(m1,m2,&c,&a,&b); res += ullMultipleMod(((m2*b)%m+m)%m, val[i], m); res %= m; } res %= m; if(res < 0) res += m; return res; } /* mod[sz-2]*mod[sz-1] < 2^62 */ /* GCD(mod[i],mod[j]) = 1, mod[i] < mod[j], i < j */ /* inv[i*sz+j] = mod[j]^(-1) (mod mod[i]), j < i */ ll llChaineseRemainderTheorem_Garner(ll val[], ll mod[], ll inv[], ll last_mod, int sz, ll *mem){ int i, j; ll k; rep(i,sz) mem[i] = val[i]; rep(i,sz) rep(j,i){ k = (mem[i]-mem[j]+mod[i])%mod[i]; mem[i] = (k*inv[i*sz+j])%mod[i]; } k = 0; for(i=sz-1;i>=0;i--){ k = ullMultipleMod(mod[i]%last_mod,k,last_mod) + mem[i]; k %= last_mod; } return k; } ll llChineseRemainderTheorem_slow(ll val[], ll mod[], int sz){ int i, j; ll res; rep(i,sz) REP(j,i+1,sz) assert( llGCD(mod[i],mod[j])==1 ); rep(i,sz) assert( 0<=val[i]&&val[i]=n) break; assert((1<=2; m/=2){ mh = m/2; rep(i,mh){ w = ((ll)i*th)%n; for(j=i;j(i^=k); k/=2); if(j= n */ /* size(a), size(b) >= 2^(k+1) */ /* res[k] = a[k]*b[0] + a[k-1]*b[1] + ... + a[0]*b[k] % mod, (a[n] = b[n] = a[n+1] = b[n+1] = ... = 0) */ /* mod is a prime, primitive_root is its primitive root */ void convolution(int a[], int b[], int n, int mod, int primitive_root, int res[], void *mem){ int i, j, k, inv; int *A, *B; for(k=0;;k++) if(n <= (1<a) return 0; res = ullMultipleMod(small_fact[a]%mod, small_fact_inv[b]%mod, mod); res = ullMultipleMod(res, small_fact_inv[a-b]%mod, mod); return res; } /* get a such that: P(x) = sum[k=0..d] a[k] * (x!/k!/(x-k)!) */ /* a[k] = sum[j=0..k] (-1)^(k-j) Comb(k,j) P(j) */ void polyValueToCoef(ll P[], int D, ll res[], ll M, void *mem){ int i; static ll b[100000], c[100000]; rep(i,D+1){ b[i] = small_fact_inv[i] % M; if(i%2) b[i] = (M - b[i])%M; c[i] = ullMultipleMod(P[i] % M, small_fact_inv[i] % M, M); } myComvolution(b,c,D+1,res,M,mem); rep(i,D+1) res[i] = ullMultipleMod(res[i], small_fact[i]%M, M); } ll solve1(ll P[], int D, char N[], ll iN, ll Q, ll M, void *mem){ int i, j, k, len; ll pwQ[11]; ll res = 0; static ll Pm[100000], a[100000], b[100000], c[100000], y[100000]; ll q_inv, sum, mul, tmp; if(M==1) return 0; rep(i,D+1) Pm[i] = P[i] % M; polyValueToCoef(Pm, D, a, M, mem); q_inv = get_inv(Q-1, M); c[0] = (M-q_inv)%M; REP(i,1,D+1){ c[i] = ullMultipleMod(c[i-1], Q%M, M); c[i] = ullMultipleMod(c[i], q_inv, M); c[i] = (M-c[i])%M; } /* sum[j=0..d] a[j] * Q^j * (1-Q)^(-j-1) */ rep(j,D+1){ res += ullMultipleMod(a[j], c[j], M); res %= M; } /* - Q^n sum[0<=k<=j<=d] a[j]*Comb(n,k)*Q^(j-k)*(1-Q)^(k-j-1) */ b[0] = 1; REP(i,1,D+1){ b[i] = ullMultipleMod(b[i-1], ((iN-i+1)%M+M)%M, M); b[i] = ullMultipleMod(b[i], small_inv[i]%M, M); } myComvolution(b,c,D+1,y,M,mem); sum = 0; /* mul = ullPowMod(Q%M, N, M);*/ mul = 1; pwQ[0] = 1; REP(i,1,10) pwQ[i] = ullMultipleMod(pwQ[i-1], Q%M, M); len = strlen(N); rep(i,len) mul = ullMultipleMod(ullPowMod(mul, 10, M), pwQ[N[i]-'0'], M); rep(i,D+1){ sum += ullMultipleMod(a[i], y[i], M); sum %= M; } sum = (M-sum)%M; res += ullMultipleMod(sum,mul,M); res %= M; return res; } ll solve2(ll P[], int D, char N[], ll iN, ll Q, ll M, void *mem){ int i, j, k, a; ll res = 0; static ll comb_memo[100000], T[100000]; static ll b[100000], c[100000], t[100000]; ll rem, add, mul; if(M==1) return 0; /* a is the minimum integer such that (Q-1)^a % M = 0 */ for(a=0;;a++){ rem = ullPowMod((Q-1)%M, a, M); if(!rem) break; } rep(i,D+2) comb_memo[i] = smallComb(D+1, i, M); REP(i,D+1,D+a){ P[i] = 0; REP(j,1,D+2){ add = ullMultipleMod(comb_memo[j], P[i-j]%M, M); if(j%2==1) P[i] += add; else P[i] -= add; P[i] %= M; } if(P[i] < 0) P[i] += M; } mul = 1; rep(i,D+a){ T[i] = ullMultipleMod(P[i]%M, mul, M); mul = ullMultipleMod(mul, Q%M, M); } polyValueToCoef(T, D+a-1, t, M, mem); mul = iN%M; rep(i,D+a){ res += ullMultipleMod(t[i], mul, M); res %= M; mul = ullMultipleMod(mul, ((iN-i-1)%M+M)%M, M); mul = ullMultipleMod(mul, small_inv[i+2]%M, M); } return res; } int main(){ int T; ll M, Q; int D, sumD = 0; static ll P[21000]; char N[1000000]; ull iN; /* N mod M */ int i, j, k, len, lenSum = 0; static ll a[100000], b[100000], c[100000]; ll M1, M2, m; ll res, res1, res2; void *mem = malloc(40*1000000); myConvolutionInit(); assert( scanf("%d",&T)==1 ); assert( 1<=T && T<=5000 ); while(T--){ assert( scanf("%lld%lld%s%d\n",&M,&Q,N,&D)==4 ); assert( 1LL