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

本文详细介绍了序列求和的五种版本(V1到V5),包括拉格朗日插值法、递推公式推导、斐波那契数列的应用以及微扰法证明。针对不同情况,给出了相应的算法思路和复杂度分析,如V2中的O(k)递推和V5中的多项式求解技巧。
摘要由CSDN通过智能技术生成

序列求和 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<bits/stdc++.h>
#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<bits/stdc++.h>
#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<bits/stdc++.h>
#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<bits/stdc++.h>
#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<bits/stdc++.h>
#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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值