传送门
题解:
我们要求的是这个东西:
A
n
s
=
∑
i
=
0
n
(
n
i
)
s
i
⋅
a
i
%
4
Ans=\sum_{i=0}^n{n\choose i}s^i\cdot a_{i\%4}
Ans=i=0∑n(in)si⋅ai%4
首先我们有单位根的性质: [ n ∣ k ] = 1 n ∑ i = 0 n − 1 ω n i k [n\mid k]=\frac{1}{n}\sum_{i=0}^{n-1}\omega_{n}^{ik} [n∣k]=n1i=0∑n−1ωnik
我们考虑求一个数列 { a } \{a\} {a}的所有 k k k的倍数项之和。令其生成函数为 A ( x ) = ∑ i = 0 n a i x i A(x)=\sum\limits_{i=0}^{n} a_ix^i A(x)=i=0∑naixi
那么我们有 ∑ i = 0 n a i [ k ∣ i ] = 1 k ∑ i = 0 k − 1 A ( ω k i ) \sum_{i=0}^{n} a_i[k\mid i]=\frac{1}{k}\sum_{i=0}^{k-1}A(\omega_{k}^i) i=0∑nai[k∣i]=k1i=0∑k−1A(ωki)
如果 A ( ω k i ) A(\omega_{k}^i) A(ωki)有什么快速计算方式的话就可以优化复杂度了。
以上就是单位根反演的理论基础。
在这道题中我们先将上面的式子进行一点转化:
A n s = ∑ d = 0 3 a d ∑ i = 0 n ( n i ) s i [ i % 4 = d ] Ans=\sum_{d=0}^3a_d\sum_{i=0}^n{n\choose i}s^i[i\%4=d] Ans=d=0∑3adi=0∑n(in)si[i%4=d]
先不管那个 d d d,我们考虑 d = 0 d=0 d=0的时候怎么做。
我们要求 ∑ i = 0 n ( n i ) s n − i [ 4 ∣ i ] \sum_{i=0}^n{n\choose i}s^{n-i}[4\mid i] i=0∑n(in)sn−i[4∣i]
令 a i = ( n i ) s n − i a_i={n\choose i}s^{n-i} ai=(in)sn−i,注意这里翻转了一下,则我们由二项式定理知道: A ( x ) = ( x + s ) n A(x)=(x+s)^n A(x)=(x+s)n
于是
∑ i = 0 n ( n i ) s n − i [ 4 ∣ i ] = 1 4 ∑ i = 0 3 ( ω 4 i + s ) n \begin{aligned} \sum_{i=0}^n{n\choose i}s^{n-i}[4\mid i]&=&\frac{1}{4}\sum_{i=0}^{3}(\omega_4^i+s)^n \end{aligned} i=0∑n(in)sn−i[4∣i]=41i=0∑3(ω4i+s)n
于是可以直接快速幂解决。
那么当 d d d不为 0 0 0的情况呢?
生成函数系数平移啊,也就是乘上若干个
x
x
x。
于是乎,很愉快地,我们的答案出来了:
1 4 ∑ d = 0 3 a ( n + d ) % 4 ∑ i = 0 3 ( ω 4 i + s ) n ω 4 d i \frac{1}{4}\sum_{d=0}^3a_{(n+d)\%4}\sum_{i=0}^3(\omega_4^i+s)^n\omega_{4}^{di} 41d=0∑3a(n+d)%4i=0∑3(ω4i+s)nω4di
快速幂+递推就行了。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
cs int mod=998244353,inv4=748683265;
cs int w0=1,w1=911660635,w2=998244352,w3=86583718;
inline int add(int a,int b){return (a+=b)>=mod?a-mod:a;}
inline void Inc(int &a,int b){(a+=b)>=mod&&(a-=mod);}
inline int mul(int a,int b){ll r=(ll)a*b;return r>=mod?r%mod:r;}
inline int power(int a,int b,int res=1){
for(;b;b>>=1,a=mul(a,a))(b&1)&&(res=mul(res,a));
return res;
}
ll n;
int nn,s,a[4],T;
int f0,f1,f2,f3,res;
signed main(){
scanf("%d",&T);
while(T--){
scanf("%lld%d%d%d%d%d",&n,&s,&a[0],&a[1],&a[2],&a[3]);
res=0,nn=n%(mod-1);
f0=power(add(w0,s),nn);
f1=power(add(w1,s),nn);
f2=power(add(w2,s),nn);
f3=power(add(w3,s),nn);
Inc(res,mul(a[nn&3],add(add(f0,f1),add(f2,f3))));
f1=mul(f1,w1);f2=mul(f2,w2);f3=mul(f3,w3);
Inc(res,mul(a[nn+1&3],add(add(f0,f1),add(f2,f3))));
f1=mul(f1,w1);f2=mul(f2,w2);f3=mul(f3,w3);
Inc(res,mul(a[nn+2&3],add(add(f0,f1),add(f2,f3))));
f1=mul(f1,w1);f2=mul(f2,w2);f3=mul(f3,w3);
Inc(res,mul(a[nn+3&3],add(add(f0,f1),add(f2,f3))));
std::cout<<mul(res,inv4)<<"\n";
}
return 0;
}