题目描述
一行三个正整数 ,表示L,R,K,含义如题所示。
分析
这道题实际上就是逗你玩的,求的就是自然数幂和
∑ri=lik
,当然,如果l=1,你还要给答案加上
2k−1
我们新学习一个插值法…
拉格朗日插值法
背诵吧…反正用处也不广,记证明没什么用。
我们如果知道函数有多项式解析式,若是K+1次,那么我们用K+2个函数点,用插值法,就可以唯一确定解析式。而拉格朗日插值法由于式子长得好看,别的方法弄自然数幂和都要
O(K2)
,他只要
O(K或者你比较懒KlogK)
对于K+2个函数点
(xi,yi)
,我们知道通项公式是K+1次的话:
我们如果要求自变量x的函数值,那么
y(x)=∑K+2i=1yi∗∏K+2j=1,j≠ix−xjxi−xj
.
对于一次代入,可以发现后面的累乘可以预处理,因为分子和分母都是一段连续的数,挖掉一个数再相乘的积。
要预处理每个数的逆元,求函数值,用快速幂就带log了,有不用的方法。
代码
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<set>
using namespace std;
#define fo(i,j,k) for(i=j;i<=k;i++)
#define fd(i,j,k) for(i=j;i>=k;i--)
#define cmax(a,b) (a=(a>b)?a:b)
typedef long long ll;
typedef double db;
const int N=1e6+50,mo=998244353;
int rev[N],y[N],prev[N],nrev[N],a[N],b[N],c[N],l,r,K,i,j,k,ans;
int ksm(int x,int y)
{
int ret=1;
while (y)
{
if (y&1) ret=1ll*ret*x%mo;
x=1ll*x*x%mo;
y>>=1;
}
return ret;
}
void predo()
{
fo(i,1,K+2) rev[i]=ksm(i,mo-2);
fo(i,1,K+2) y[i]=(y[i-1]+ksm(i,K))%mo;
prev[0]=nrev[0]=1;
fo(i,1,K+2)
{
prev[i]=1ll*prev[i-1]*rev[i]%mo;
nrev[i]=1ll*nrev[i-1]*(-rev[i])%mo;
}
}
int get(int x)
{
if (x<=K+2) return y[x];
b[0]=1;
fo(i,1,K+2) a[i]=x-i,b[i]=1ll*b[i-1]*a[i]%mo;
c[K+3]=1;
fd(i,K+2,1) c[i]=1ll*c[i+1]*a[i]%mo;
int ret=0;
fo(i,1,K+2)
ret=(ret+1ll*y[i]*b[i-1]%mo*c[i+1]%mo*prev[i-1]%mo*nrev[K+2-i])%mo;
return ret;
}
int main()
{
freopen("t1.in","r",stdin);
// freopen("count.out","w",stdout);
scanf("%d %d %d",&l,&r,&K);
predo();
ans=(get(r)-get(l-1)+mo)%mo;
if (l==1) ans=(ans+ksm(2,K)-1)%mo;
printf("%d\n",ans);
}