1822 序列求和V5

若R≡0R≡0,那么显然答案就为0.
  接下来,我们用符号fk(n)fk(n)代表我们所要求的值。首先我们要预处理fk(1),⋯,fk(k+1)fk(1),⋯,fk(k+1)的值,由于xkxk是一个完全积性函数,利用线性筛,这一预处理可以很容易在O(k)O(k)的时间内完成。
  若R≡1R≡1,则原问题转化为求∑ni=1ik∑i=1nik的值,我们知道,这时fk(n)fk(n)是关于nn的k+1k+1次多项式。同时,我们也知道,n≥k+1n≥k+1时,每一个CinCni都是关于nn的ii次多项式,并且它们线性无关,而n≤kn≤k时,可以O(1)O(1)直接查询。对于n≥k+1n≥k+1的情况,我们用C0n,⋯,Ck+1nCn0,⋯,Cnk+1这k+2k+2个数来线性表出fk(n)fk(n),设fk(n)=∑k+1i=0Cinaifk(n)=∑i=0k+1Cniai,根据二项式反演,有an=∑ni=0(−1)n−iCinfk(i)an=∑i=0n(−1)n−iCnifk(i)。
  这里先写一个引理:∑ki=0(−1)iCin=(−1)kCkn−1∑i=0k(−1)iCni=(−1)kCn−1k,这个很好证我就不写了。
  将anan代回原式得:
fk(n)=∑i=0k+1Cin∑j=0i(−1)i−jCjifk(j)=∑i=0k+1fk(i)∑j=ik+1(−1)j−iCjnCij=∑i=0k+1fk(i)Cin∑j=ik+1(−1)j−iCj−in−i=∑i=0k+1fk(i)Cin∑j=0k−i+1(−1)jCjn−i=∑i=0k+1(−1)k−i+1CinCk−i+1n−i−1=∑i=0k+1∏0≤j≤k+1,j≠in−ji!(k−i+1)!
fk(n)=∑i=0k+1Cni∑j=0i(−1)i−jCijfk(j)=∑i=0k+1fk(i)∑j=ik+1(−1)j−iCnjCji=∑i=0k+1fk(i)Cni∑j=ik+1(−1)j−iCn−ij−i=∑i=0k+1fk(i)Cni∑j=0k−i+1(−1)jCn−ij=∑i=0k+1(−1)k−i+1CniCn−i−1k−i+1=∑i=0k+1∏0≤j≤k+1,j≠in−ji!(k−i+1)!
  这样,分子和分母的部分都可以预处理出来,复杂度O(k)O(k)。
  若R≢1R≢1,有:
(R−1)fk(n)∴fk(n)=(R−1)∑i=1nikRi=∑i=1nikRi+1−∑i=1nikRi=∑i=1n+1(i−1)kRi−∑i=1nikRi=nkRn+1−∑i=1n∑j=0k−1(−1)k−j−1CjkijRi=nkRn+1−∑j=0k−1(−1)k−j+1Cjkfj(n)=nkRn+1−∑k−1j=0(−1)k−j+1Cjkfj(n)R−1
(R−1)fk(n)=(R−1)∑i=1nikRi=∑i=1nikRi+1−∑i=1nikRi=∑i=1n+1(i−1)kRi−∑i=1nikRi=nkRn+1−∑i=1n∑j=0k−1(−1)k−j−1CkjijRi=nkRn+1−∑j=0k−1(−1)k−j+1Ckjfj(n)∴fk(n)=nkRn+1−∑j=0k−1(−1)k−j+1Ckjfj(n)R−1
  下面我们证明一个结论,对∀fi(n),0≤i≤k,∃Fi(n)∈Qi[x]∀fi(n),0≤i≤k,∃Fi(n)∈Qi[x],有fi(n)=Rn+1Fi(n)−RFi(0)fi(n)=Rn+1Fi(n)−RFi(0)。
证明:当i当ifk(n)这样,=0时,结论已经成立(请自行验证)=k时,假设结论对0,⋯,k−1均成立=nkRn+1−∑k−1j=0(−1)k−j+1Cjkfj(n)R−1=nkRn+1−∑k−1j=0(−1)k−j+1Cjk[Rn+1Fj(n)−RFj(0)]R−1=Rn+1[nk−∑k−1j=0(−1)k−j+1CkjFj(n)]+R[∑k−1j=0(−1)k−j+1CjkFj(0)]R−1我们令Fk(n)=nk−∑j=0k−1(−1)k−j+1CkjFj(n),容易验证它满足题目要求。
证明:当i=0时,结论已经成立(请自行验证)当i=k时,假设结论对0,⋯,k−1均成立fk(n)=nkRn+1−∑j=0k−1(−1)k−j+1Ckjfj(n)R−1=nkRn+1−∑j=0k−1(−1)k−j+1Ckj[Rn+1Fj(n)−RFj(0)]R−1=Rn+1[nk−∑j=0k−1(−1)k−j+1CjkFj(n)]+R[∑j=0k−1(−1)k−j+1CkjFj(0)]R−1这样,我们令Fk(n)=nk−∑j=0k−1(−1)k−j+1CjkFj(n),容易验证它满足题目要求。

  我们再来证明一个引理:对 ∀0≤m≤k,∑ki=0(−1)iCikCmi=0∀0≤m≤k,∑i=0k(−1)iCkiCim=0
证明:∑i=0k(−1)iCikCmi=∑i=0k(−1)iCmkCi−mk−m=Cmk∑i=0k−m(−1)i+mCik−m=Cmk(−1)m(1−1)(k−m)=0
证明:∑i=0k(−1)iCkiCim=∑i=0k(−1)iCkmCk−mi−m=Ckm∑i=0k−m(−1)i+mCk−mi=Ckm(−1)m(1−1)(k−m)=0

  在上一部分的讨论中,我们已经知道,作为一个 kk次多项式,Fk(n)Fk(n)可以表示为 C0n,⋯,CknCn0,⋯,Cnk的线性组合。设 Fk(n)=∑ki=0CinaiFk(n)=∑i=0kCniai,则
∑i=0k(−1)iCikFk(n)=∑i=0k(−1)iCik∑j=0kCjiaj=∑j=0k∑i=0k(−1)iCikCjiaj=∑j=0k0=0
∑i=0k(−1)iCkiFk(n)=∑i=0k(−1)iCki∑j=0kCijaj=∑j=0k∑i=0k(−1)iCkiCijaj=∑j=0k0=0

  我们又有:
(n+1)kRn+1∴Fk(n+1)=fk(n+1)−fk(n)=Rn+2Fk(n+1)−Rn+1+RFk(0)=(n+1)k+Fk(n)R
(n+1)kRn+1=fk(n+1)−fk(n)=Rn+2Fk(n+1)−Rn+1+RFk(0)∴Fk(n+1)=(n+1)k+Fk(n)R

  通过上面两个等式,我们就可以通过解一个一元一次方程来得到 Fk(0),⋯,Fk(k)Fk(0),⋯,Fk(k)的值,之后我们用拉格朗日插值公式就可以 O(k)O(k)地得到 Fk(n)Fk(n)的值,再代回原式,这道题就解决了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <ctime>
#include <vector>
#include <set>
//#define ivorysi
#define eps 1e-8
#define mo 974711
#define pb push_back
#define mp make_pair
#define pii pair<int,int>
#define fi first
#define se second
#define MAXN 200005
#define space putchar(' ')
#define enter putchar('\n')
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < '0' || c > '9') {
    if(c == '-') f = -1;
    c = getchar();
    }
    while(c >= '0' && c <= '9') {
    res = res * 10 + c - '0';
    c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) putchar('-');
    if(x >= 10) {
    out(x / 10);
    }
    putchar('0' + x % 10);
}
const int64 MOD = 985661441;
int64 fpow(int64 x,int64 c) {
    int64 res = 1,t = x;
    while(c) {
    if(c & 1) res = res * t % MOD;
    t = t * t % MOD;
    c >>= 1;
    }
    return res;
}

int T,K;
int prime[MAXN],tot;
int64 N,R,F[MAXN];
int64 a[MAXN],b[MAXN];
int64 MK[MAXN];
int64 fac[MAXN],invfac[MAXN],Le[MAXN],Ri[MAXN];
bool nonprime[MAXN];
int64 C(int n,int m) {
    if(n < m) return 0;
    return fac[n] * invfac[n - m] % MOD * invfac[m] % MOD;
}
void Solve() {
    read(K);read(N);read(R);
    R %= MOD;
    if(R == 0) {puts("0");return;}   
    MK[1] = 1;
    memset(nonprime,0,sizeof(nonprime));
    tot = 0;
    for(int i = 2 ; i <= K + 2 ; ++i) {
    if(!nonprime[i]) {
        prime[++tot] = i;
        MK[i] = fpow(i,K); 
    }
    for(int j = 1 ; j <= tot ; ++j) {
        if(prime[j] > (K + 2) / i) break;
        nonprime[i * prime[j]] = 1;
        MK[i * prime[j]] = MK[i] * MK[prime[j]] % MOD;
        if(i % prime[j] == 0) break;
    }
    }
    if(R == 1) {
    F[0] = 0;
    for(int i = 1 ; i <= K + 2 ; ++i) F[i] = (F[i - 1] + MK[i]) % MOD;
    if(N <= K + 2) {out(F[N]);enter;return;}
    int64 t = 1,ans = 0;
    Le[0] = 1;
    N %= MOD;
    for(int i = 1 ; i <= K + 2 ; ++i) {
        Le[i] = Le[i - 1] * (N + MOD - i) % MOD;
    }
    Ri[K + 3] = 1;
    for(int i = K + 2 ; i >= 1 ; --i) {
        Ri[i] = Ri[i + 1] * (N + MOD - i) % MOD;
    }
    for(int i = K + 2 ; i >= 1 ; --i) {
        ans += t * invfac[i - 1] % MOD * invfac[K + 2 - i] % MOD * Le[i - 1] % MOD * Ri[i + 1] % MOD * F[i] % MOD;
        t = t * (MOD - 1) % MOD;
    }
    ans %= MOD;
    out(ans);enter;return;
    }
    a[0] = 1,b[0] = 0;
    int64 InvR = fpow(R,MOD - 2);
    for(int i = 1 ; i <= K + 1; ++i) {
    a[i] = 1LL * a[i - 1] * InvR % MOD;
    b[i] = (1LL * b[i - 1] * InvR + MK[i]) % MOD;
    }
    int64 suma = 0,sumb = 0,t = 1;
    if(K & 1) t = MOD - 1;
    for(int i = 0 ; i <= K + 1; ++i) {
    int64 h = t * C(K + 1,i) % MOD;
    suma = (suma + a[i] * h) % MOD;
    sumb = (sumb + b[i] * h) % MOD;
    t = t * (MOD - 1) % MOD;
    }
    F[0] = (MOD - sumb) * fpow(suma,MOD - 2) % MOD;
    for(int i = 1 ; i <= K + 1; ++i) F[i] = (a[i] * F[0] + b[i]) % MOD;
    int64 ans = 0;
    t = 1;
    if(N <= K) {
    ans = (fpow(R,N) * F[N] - F[0] + MOD) % MOD;
    out(ans);enter;
    return ;
    }
    int64 T = N % (MOD - 1);
    N %= MOD;
    Le[0] = N;
    for(int i = 1 ; i <= K ; ++i) {
    Le[i] = Le[i - 1] * (N + MOD - i) % MOD;
    }
    Ri[K + 1] = 1;
    for(int i = K ; i >= 0 ; --i) {
    Ri[i] = Ri[i + 1] * (N + MOD - i) % MOD;
    }
    if(K & 1) t = MOD - 1;
    for(int i = 0 ; i <= K; ++i) {
    int64 h;
    if(i == 0) h = t * invfac[i] % MOD * invfac[K - i] % MOD * Ri[i + 1] % MOD * F[i] % MOD;
    else h = t * invfac[i] % MOD * invfac[K - i] % MOD * Le[i - 1] % MOD * Ri[i + 1] % MOD * F[i] % MOD;
    t = t * (MOD - 1) % MOD;
    ans += h;
    }
    ans %= MOD;
    ans = (ans * fpow(R,T) - F[0] + MOD) % MOD;
    out(ans);enter;
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    fac[0] = 1;
    for(int i = 1 ; i <= 200001 ; ++i) fac[i] = fac[i - 1] * i % MOD;
    invfac[200001] = fpow(fac[200001],MOD - 2);
    for(int i = 200000 ; i >= 0 ; --i) invfac[i] = invfac[i + 1] * (i + 1) % MOD;
    read(T);
    while(T--) {
    Solve();
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值