51nod 序列求和系列 简要题解

文章目录

    • 序列求和 V1
    • 序列求和 V2
    • 序列求和 V3
    • 序列求和 V4
    • 序列求和 V5

序列求和 V1

传送门
有个显然的结论是 S ( n ) = ∑ i = 1 n i k S(n)=\sum_{i=1}^ni^k S(n)=i=1nik k + 1 k+1 k+1 次多项式,证明可以用差分。
于是直接上拉格朗日插值即可。
CODE:

#include
#define ri register int
using namespace std;
typedef long long ll;
const int rlen=1<<18|1;
char buf[rlen],*ib=buf,*ob=buf;
#define gc() (((ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin)),ib==ob)?-1:*ib++)
inline int read(){
	int ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
}
inline ll readl(){
	ll ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
}
const int mod=1e9+7;
inline int add(int a,int b){return (a+=b)<mod?a:a-mod;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline int mul(int a,int b){return (ll)a*b%mod;}
inline void Add(int&a,int b){(a+=b)<mod?0:(a-=mod);}
inline void Dec(int&a,int b){(a-=b)<0?(a+=mod):a;}
inline void Mul(int&a,int b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,Mul(a,a))(p&1)&&(Mul(ret,a),1);return ret;}
const int N=2005;
int n,k,f[N],fac[N],ifac[N];
inline void init(int n){
	fac[0]=fac[1]=ifac[0]=ifac[1]=1;
	for(ri i=2;i<=n;++i)fac[i]=mul(fac[i-1],i),ifac[i]=mul(ifac[mod-mod/i*i],mod-mod/i);
	for(ri i=2;i<=n;++i)Mul(ifac[i],ifac[i-1]);
}
inline int lagrange(int*f,int up,int x0){
	static int pre[N],suf[N];
	if(x0<=up)return f[x0];
	int res=0;
	pre[0]=suf[up+1]=1;
	for(ri i=1;i<=up;++i)pre[i]=mul(pre[i-1],x0-i);
	for(ri i=up;i;--i)suf[i]=mul(suf[i+1],x0-i);
	for(ri i=1,t;i<=up;++i){
		t=mul(f[i],mul(mul(pre[i-1],suf[i+1]),mul(ifac[i-1],ifac[up-i])));
		(up-i)&1?Dec(res,t):Add(res,t);
	}
	return res;
}
int main(){
	#ifdef ldxcaicai
	freopen("lx.in","r",stdin);
	#endif
	init(2001);
	for(ri tt=read();tt;--tt){
		n=readl()%mod,k=read();
		for(ri i=1;i<=k+2;++i)f[i]=add(f[i-1],ksm(i,k));
		cout<<lagrange(f,k+2,n)<<'\n';
	}
	return 0;
}

序列求和 V2

传送门
要求的东西是跟 V 4 V4 V4 一毛一样的,但这里给出一种与众不同的推式子方法:

S ( n ) = ∑ i = 1 n r i i k = ∑ i = 1 n r i ∑ j = 1 i S k , j C i , j j ! = ∑ i = 1 k S k , i i ! ∑ j = 1 n r j C j , i 令 f ( x ) = ∑ i = 1 n r i C i , x f ( x ) = ∑ i = 1 n r i ( C i − 1 , x + C i − 1 , x − 1 ) = r ( ∑ i = 1 n r i C i , x − r n C n , x + r 0 C 0 , x + ∑ i = 1 n r i C i , x − 1 − r n C n , x − 1 + r 0 C 0 , x − 1 ) = r ( f ( x ) + f ( x − 1 ) − r n C n + 1 , x + C 1 , x ) ⇒ f ( x ) = r r − 1 ( r n C n + 1 , x − C 1 , x − f ( x − 1 ) ) \begin{aligned}S(n)=&\sum\limits_{i=1}^nr^ii^k\\=&\sum\limits_{i=1}^nr^i\sum\limits_{j=1}^iS_{k,j}C_{i,j}j!\\=&\sum\limits_{i=1}^kS_{k,i}i!\sum\limits_{j=1}^nr^jC_{j,i}\\令f(x)=&\sum\limits_{i=1}^nr^iC_{i,x}\\f(x)=&\sum\limits_{i=1}^nr^i(C_{i-1,x}+C_{i-1,x-1})\\=&r(\sum\limits_{i=1}^nr^iC_{i,x}-r^nC_{n,x}+r^0C_{0,x}+\sum\limits_{i=1}^nr^iC_{i,x-1}-r^nC_{n,x-1}+r^0C_{0,x-1})\\=&r(f(x)+f(x-1)-r^nC_{n+1,x}+C_{1,x})\\\Rightarrow f(x)=&\frac r{r-1}(r^nC_{n+1,x}-C_{1,x}-f(x-1))\end{aligned} S(n)===f(x)=f(x)===f(x)=i=1nriiki=1nrij=1iSk,jCi,jj!i=1kSk,ii!j=1nrjCj,ii=1nriCi,xi=1nri(Ci1,x+Ci1,x1)r(i=1nriCi,xrnCn,x+r0C0,x+i=1nriCi,x1rnCn,x1+r0C0,x1)r(f(x)+f(x1)rnCn+1,x+C1,x)r1r(rnCn+1,xC1,xf(x1))
特判掉 r = 1 r=1 r=1 的情况,就能够 O ( k ) O(k) O(k) 递推出整个 f f f 数组,由于模数不友好可以 O ( k 2 ) O(k^2) O(k2) 预处理出第二类斯特林数
时间复杂度 O ( k 2 + T k ) O(k^2+Tk) O(k2+Tk)
CODE:

#include
#define ri register int
using namespace std;
typedef long long ll;
const int rlen=1<<18|1;
char buf[rlen],*ib=buf,*ob=buf;
#define gc() (((ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin)),ib==ob)?-1:*ib++)
inline int read(){
	int ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
}
inline ll readl(){
	ll ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
}
const int mod=1e9+7;
inline int add(int a,int b){return (a+=b)<mod?a:a-mod;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline int mul(int a,int b){return (ll)a*b%mod;}
inline void Add(int&a,int b){(a+=b)<mod?0:(a-=mod);}
inline void Dec(int&a,int b){(a-=b)<0?(a+=mod):a;}
inline void Mul(int&a,int b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,Mul(a,a))(p&1)&&(Mul(ret,a),1);return ret;}
const int N=2005;
int k,r,S[N][N],fac[N],ifac[N],m,f[N];
ll n;
inline int C(int n,int m){return n<m||m<0?0:mul(fac[n],mul(ifac[m],ifac[n-m]));}
inline void init(int n){
	S[0][0]=1;
	for(ri i=1;i<=n;++i)for(ri j=1;j<=i;++j)S[i][j]=add(S[i-1][j-1],mul(S[i-1][j],j));
	fac[0]=fac[1]=ifac[0]=ifac[1]=1;
	for(ri i=2;i<=n;++i)fac[i]=mul(fac[i-1],i),ifac[i]=mul(ifac[mod-mod/i*i],mod-mod/i);
	for(ri i=2;i<=n;++i)Mul(ifac[i],ifac[i-1]);
}
int main(){
	#ifdef ldxcaicai
	freopen("lx.in","r",stdin);
	#endif
	init(2001);
	for(ri res=0,tt=read();tt;--tt,res=0){
		n=readl(),k=read(),r=readl()%mod;
		m=n%(mod-1);
		n%=mod;
		f[0]=r==1?n:dec(mul(dec(ksm(r,m+1),1),ksm(dec(r,1),mod-2)),1);
		for(ri c1=mul(r,ksm(dec(r,1),mod-2)),c2=ksm(r,m),mt=n+1,i=1;i<=k;Mul(mt,dec(n+1,i++))){
			if(r^1)f[i]=mul(c1,dec(mul(c2,mul(mt,ifac[i])),add(C(1,i),f[i-1])));
			else f[i]=dec(mul(mt,mul(dec(n+1,i),ifac[i+1])),C(1,i+1));
			Add(res,mul(f[i],mul(S[k][i],fac[i])));
		}
		cout<<res<<'\n';
	}
	return 0;
}

序列求和 V3

传送门
s b t sbt sbt直接上式子吧(以下用 f i b i fib_i fibi 表示斐波那契数列第 i i i 项):
A n s = ∑ i = 1 n f i b i k = ∑ i = 1 n ( ( 1 + 5 2 ) i − ( 1 − 5 2 ) i 5 ) k 令 X = 1 + 5 2 , Y = 1 − 5 2 = 1 ( 5 ) k ∑ i = 1 n ∑ j = 0 k ( X i ) j ( Y i ) k − j = 1 ( 5 ) k ∑ j = 0 k ∑ i = 1 n ( X j Y k − j ) i \begin{aligned}Ans=&\sum\limits_{i=1}^nfib_i^k\\=&\sum\limits_{i=1}^n(\frac{(\frac{1+\sqrt5}2)^i-(\frac{1-\sqrt5}2)^i}{\sqrt5})^k\\令X=&\frac{1+\sqrt5}2,Y=\frac{1-\sqrt5}2\\=&\frac1{(\sqrt5)^k}\sum\limits_{i=1}^n\sum\limits_{j=0}^k(X^i)^j(Y^i)^{k-j}\\=&\frac1{(\sqrt5)^k}\sum\limits_{j=0}^k\sum\limits_{i=1}^n(X^jY^{k-j})^i\end{aligned} Ans==X===i=1nfibiki=1n(5 (21+5 )i(215 )i)k21+5 ,Y=215 (5 )k1i=1nj=0k(Xi)j(Yi)kj(5 )k1j=0ki=1n(XjYkj)i
发现枚举 k k k 之后就是等比数列求和,搞定
然后注意模数是 1 e 9 + 9 1e9+9 1e9+9 而不是 1 e 9 + 7 1e9+7 1e9+7 因此这个时候 5 \sqrt5 5 是有意义的可以直接暴力枚举出来而不用重新定义一个结构体记录虚实部
CODE:

#include
#define ri register int
using namespace std;
typedef long long ll;
const int rlen=1<<18|1;
char buf[rlen],*ib=buf,*ob=buf;
#define gc() (((ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin)),ib==ob)?-1:*ib++)
inline int read(){
	int ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
}
inline ll readl(){
	ll ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
}
const int mod=1e9+9,sqrt5=383008016,w1=691504013,w2=308495997,INV=276601605;
inline int add(int a,int b){return (a+=b)<mod?a:a-mod;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline int mul(int a,int b){return (ll)a*b%mod;}
inline void Add(int&a,int b){(a+=b)<mod?0:(a-=mod);}
inline void Dec(int&a,int b){(a-=b)<0?(a+=mod):a;}
inline void Mul(int&a,int b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,Mul(a,a))(p&1)&&(Mul(ret,a),1);return ret;}
const int N=1e5+5;
int fac[N],ifac[N],mt1[N],mt2[N],iv[N];
inline int C(int n,int m){return n<m||m<0?0:mul(fac[n],mul(ifac[m],ifac[n-m]));}
inline void init(int n){
	fac[0]=fac[1]=ifac[0]=ifac[1]=1;
	for(ri i=2;i<=n;++i)fac[i]=mul(fac[i-1],i),ifac[i]=mul(ifac[mod-mod/i*i],mod-mod/i);
	for(ri i=2;i<=n;++i)Mul(ifac[i],ifac[i-1]);
	mt1[0]=mt2[0]=iv[0]=1;
	for(ri i=1;i<=n;++i)mt1[i]=mul(mt1[i-1],w1),mt2[i]=mul(mt2[i-1],w2),iv[i]=mul(iv[i-1],INV);
}
ll n;
int k,n1,n2;
inline int calc(int x){return x==1?n2:dec(mul(dec(ksm(x,n1+1),1),ksm(dec(x,1),mod-2)),1);}
int main(){
	#ifdef ldxcaicai
	freopen("lx.in","r",stdin);
	#endif
	init(100000);
	for(ri res=0,tt=read();tt;--tt,res=0){
		n=readl(),k=read();
		n1=n%(mod-1),n2=n%mod;
		for(ri t=0,x;t<=k;++t){
			x=mul(C(k,t),calc(mul(mt1[k-t],mt2[t])));
			t&1?Dec(res,x):Add(res,x);
		}
		cout<<mul(res,iv[k])<<'\n';
	}
	return 0;
}

序列求和 V4

传送门
题解同序列求和 V1
就是把数组开大了一点
CODE:

#include
#define ri register int
using namespace std;
typedef long long ll;
const int rlen=1<<18|1;
char buf[rlen],*ib=buf,*ob=buf;
#define gc() (((ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin)),ib==ob)?-1:*ib++)
inline int read(){
	int ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
}
inline ll readl(){
	ll ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
}
const int mod=1e9+7;
inline int add(int a,int b){return (a+=b)<mod?a:a-mod;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline int mul(int a,int b){return (ll)a*b%mod;}
inline void Add(int&a,int b){(a+=b)<mod?0:(a-=mod);}
inline void Dec(int&a,int b){(a-=b)<0?(a+=mod):a;}
inline void Mul(int&a,int b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,Mul(a,a))(p&1)&&(Mul(ret,a),1);return ret;}
const int N=50005;
int n,k,f[N],fac[N],ifac[N];
inline void init(int n){
	fac[0]=fac[1]=ifac[0]=ifac[1]=1;
	for(ri i=2;i<=n;++i)fac[i]=mul(fac[i-1],i),ifac[i]=mul(ifac[mod-mod/i*i],mod-mod/i);
	for(ri i=2;i<=n;++i)Mul(ifac[i],ifac[i-1]);
}
inline int lagrange(int*f,int up,int x0){
	static int pre[N],suf[N];
	if(x0<=up)return f[x0];
	int res=0;
	pre[0]=suf[up+1]=1;
	for(ri i=1;i<=up;++i)pre[i]=mul(pre[i-1],x0-i);
	for(ri i=up;i;--i)suf[i]=mul(suf[i+1],x0-i);
	for(ri i=1,t;i<=up;++i){
		t=mul(f[i],mul(mul(pre[i-1],suf[i+1]),mul(ifac[i-1],ifac[up-i])));
		(up-i)&1?Dec(res,t):Add(res,t);
	}
	return res;
}
int main(){
	#ifdef ldxcaicai
	freopen("lx.in","r",stdin);
	#endif
	init(50001);
	for(ri tt=read();tt;--tt){
		n=readl()%mod,k=read();
		for(ri i=1;i<=k+2;++i)f[i]=add(f[i-1],ksm(i,k));
		cout<<lagrange(f,k+2,n)<<'\n';
	}
	return 0;
}

序列求和 V5

传送门
发现这个时候不能用 V 2 V2 V2 的做法因为不能快速预处理斯特林数,凉凉.jpg
然后现在要证明一个结论, ∀ S ( n ) = ∑ i = 0 n − 1 i k r i , ∃ g ( x )   s . t .   S ( n ) = r n g ( n ) − g ( 0 ) , deg ⁡ ( g ) ≤ k \forall S(n)=\sum\limits_{i=0}^{n-1}i^kr^i,\exists g(x)\ s.t.\ S(n)=r^ng(n)-g(0),\deg(g)\le k S(n)=i=0n1ikri,g(x) s.t. S(n)=rng(n)g(0),deg(g)k
然后下面考虑在归纳法中使用微扰法来证明这个结论:

  1. k = 0 k=0 k=0 时,显然成立
  2. k = t k=t k=t 时假设成立
  3. k = t + 1 k=t+1 k=t+1 时, r S ( n ) = ∑ i = 1 n ( i − 1 ) k r i ( r − 1 ) S ( n ) = − ∑ i = 0 n − 1 ( i k − ( i − 1 ) k ) r i + ( n − 1 ) k r n − ( − 1 ) k = r n ( n − 1 ) k − ( − 1 ) k − ( r n g ( n ) − g ( 0 ) ) 令 g ′ ( x ) = ( x − 1 ) k − g ( x ) r − 1 , 显 然 deg ⁡ ( g ′ ) ≤ k ⇒ S ( n ) = r n g ′ ( n ) − g ′ ( 0 ) \begin{aligned}rS(n)=&\sum\limits_{i=1}^{n}(i-1)^kr^i\\(r-1)S(n)=&-\sum\limits_{i=0}^{n-1}(i^k-(i-1)^k)r^i+(n-1)^kr^n-(-1)^k\\=&r^n(n-1)^k-(-1)^k-(r^ng(n)-g(0))\\令 g'(x)=&\frac{(x-1)^k-g(x)}{r-1},显然 \deg(g')\le k\\\Rightarrow S(n)=&r^ng'(n)-g'(0)&\end{aligned} rS(n)=(r1)S(n)==g(x)=S(n)=i=1n(i1)krii=0n1(ik(i1)k)ri+(n1)krn(1)krn(n1)k(1)k(rng(n)g(0))r1(x1)kg(x),deg(g)krng(n)g(0)
    得证

由此看来,要求出 S ( n + 1 ) S(n+1) S(n+1) 只需知道 g ( n + 1 ) g(n+1) g(n+1) ,既然 g ( x ) g(x) g(x) 是不超过 k k k 次的多项式,只需求出 g ( 0 ) g(0) g(0) ~ g ( k + 1 ) g(k+1) g(k+1) 即可
重新审视最初的式子并将其变形:
r n g ( n ) − g ( 0 ) = ∑ i = 0 n − 1 r i i k = ∑ i = 0 n − 2 r i i k + r n − 1 ( n − 1 ) k = r n − 1 ( g ( n − 1 ) + ( n − 1 ) k ) − g ( 0 ) ⇒ g ( n ) = g ( n − 1 ) + ( n − 1 ) k r \begin{aligned}r^ng(n)-g(0)=&\sum\limits_{i=0}^{n-1}r^ii^k\\=&\sum_{i=0}^{n-2}r^ii^k+r^{n-1}(n-1)^k\\=&r^{n-1}(g(n-1)+(n-1)^k)-g(0)\\\Rightarrow g(n)=&\frac{g(n-1)+(n-1)^k}r\end{aligned} rng(n)g(0)===g(n)=i=0n1riiki=0n2riik+rn1(n1)krn1(g(n1)+(n1)k)g(0)rg(n1)+(n1)k
这样 g ( 1 ) g(1) g(1) ~ g ( k + 1 ) g(k+1) g(k+1) 均可以用 A g ( 0 ) + B Ag(0)+B Ag(0)+B 的形式表示出来,一般解决这种问题还需要建立一个等式,对于该题可以利用 k + 1 k+1 k+1 阶差分来建立等式:
∑ i = 0 k + 1 ( − 1 ) i C k + 1 , i g ( k + 1 − i ) = 0 \sum\limits_{i=0}^{k+1}(-1)^iC_{k+1,i}g(k+1-i)=0 i=0k+1(1)iCk+1,ig(k+1i)=0
这样就能解出 g 0 g_0 g0 然后推出 g g g 1 , 2 , . . . , k + 1 1,2,...,k+1 1,2,...,k+1 项,然后利用拉格朗日插值求出 g ( n + 1 ) g(n+1) g(n+1) ,最后求出 S ( n + 1 ) S(n+1) S(n+1)
p . s . p.s. p.s. 由上面推出的结论可以知道对于 S ( n ) = ∑ i = 0 n − 1 f ( i ) r i S(n)=\sum\limits_{i=0}^{n-1}f(i)r^i S(n)=i=0n1f(i)ri ,同样存在多项式 g ( x ) g(x) g(x) 满足 r n g ( n ) − g ( 0 ) = S ( n ) r^ng(n)-g(0)=S(n) rng(n)g(0)=S(n) ,且 g g g 的次数不超过 f f f 的次数
CODE:

#include
#define ri register int
using namespace std;
typedef long long ll;
const int rlen=1<<18|1;
char buf[rlen],*ib=buf,*ob=buf;
#define gc() (((ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin)),ib==ob)?-1:*ib++)
inline int read(){
	int ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
}
inline ll readl(){
	ll ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
}
const int mod=985661441;
inline int add(int a,int b){return (a+=b)<mod?a:a-mod;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline int mul(int a,int b){return (ll)a*b%mod;}
inline void Add(int&a,int b){(a+=b)<mod?0:(a-=mod);}
inline void Dec(int&a,int b){(a-=b)<0?(a+=mod):a;}
inline void Mul(int&a,int b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,Mul(a,a))(p&1)&&(Mul(ret,a),1);return ret;}
const int N=2e5+5;
int fac[N],ifac[N];
inline int C(int n,int m){return n<m||m<0?0:mul(fac[n],mul(ifac[m],ifac[n-m]));}
inline void init(int n){
	fac[0]=fac[1]=ifac[0]=ifac[1]=1;
	for(ri i=2;i<=n;++i)fac[i]=mul(fac[i-1],i),ifac[i]=mul(ifac[mod-mod/i*i],mod-mod/i);
	for(ri i=2;i<=n;++i)Mul(ifac[i],ifac[i-1]);
}
inline int lagrange(int*a,int up,int x){
	static int pre[N],suf[N];
	if(x<=up)return a[x];
	pre[0]=suf[up+1]=1;
	for(ri i=1;i<=up;++i)pre[i]=mul(pre[i-1],x-i);
	for(ri i=up;i;--i)suf[i]=mul(suf[i+1],x-i);
	int res=0;
	for(ri t,i=1;i<=up;++i){
		t=mul(a[i],mul(mul(pre[i-1],suf[i+1]),mul(ifac[i-1],ifac[up-i])));
		(up-i)&1?Dec(res,t):Add(res,t);
	}
	return res;
}
struct F{
	int a,b;
	F(int a=0,int b=0):a(a),b(b){}
	friend inline F operator+(F a,F b){return F(add(a.a,b.a),add(a.b,b.b));}
	friend inline F operator*(F a,int b){return F(mul(a.a,b),mul(a.b,b));}
}f[N],ss;
ll n;
int k,n1,n2,r,a[N],g[N];
int main(){
	#ifdef ldxcaicai
	freopen("lx.in","r",stdin);
	#endif
	init(200001);
	for(ri tt=read();tt;--tt){
		k=read(),n=readl(),r=readl()%mod;
		if(!r){puts("0");continue;}
		for(ri i=1;i<=k+2;++i)a[i]=ksm(i,k);
		if(r==1){
			for(ri i=2;i<=k+2;++i)Add(a[i],a[i-1]);
			cout<<lagrange(a,k+2,n%mod)<<'\n';
			continue;
		}
		n1=n%mod,n2=n%(mod-1);
		f[0]=F(1,0);
		for(ri iv=ksm(r,mod-2),i=1;i<=k+1;++i)f[i]=(f[i-1]+F(0,a[i-1]))*iv;
		ss=F(0,0);
		for(ri i=0;i<=k+1;++i)ss=ss+f[k+1-i]*C(k+1,i)*(i&1?1:mod-1);
		g[0]=mul(mod-ss.b,ksm(ss.a,mod-2));
		for(ri iv=ksm(r,mod-2),i=1;i<=k+1;++i)g[i]=mul(add(g[i-1],a[i-1]),iv);
		cout<<dec(mul(lagrange(g,k+1,n1+1),ksm(r,n2+1)),g[0])<<'\n';
	}
	return 0;
}

你可能感兴趣的:(#,题解)