题目
解法
算是单位根反演的经典应用吧。先讲一个柿子
\[[n\mid k]=\frac{1}{n}\cdot \sum_{i=0}^{n-1}\omega_{n}^{ik}
\]
考虑分类讨论进行证明:
-
\(n\nmid k\)
\[\dfrac{1}{n}\cdot \sum\limits_{i=0}^{n-1}w_n^{ik}=\dfrac{1}{n}\cdot \dfrac{w_n^{nk}-1}{w_n^k-1}=0 \] -
\(n\mid k\)
\[\dfrac{1}{n}\cdot \sum\limits_{i=0}^{n-1}w_n^{ik\bmod n}=\dfrac{1}{n}\cdot \sum\limits_{i=0}^{n-1}w_n^{0}=1 \]
由这个式子可以推出 \(k\) 次多项式中 \(n\) 的倍数次项的系数和
\[\begin{align}\sum_{i=0}^{k/n}[x^{in}]f(x)&=\sum_{i=0}^k [n\mid i][x^i]f(x)\\&=\sum_{i=0}^k [x^i]f(x)\cdot \frac{1}{n}\cdot \sum_{j=0}^{n-1}\omega_{n}^{ij}\\&=\frac{1}{n}\cdot \sum_{j=0}^{n-1}(\omega_n^j)^i\cdot [x^i]f(x) \\&=\frac{1}{n}\sum_{j=0}^{n-1}f(\omega_n^j)\end{align}
\]
觉得将 \(\omega_{n}^j\) 视作带入 \(f(x)\) 的自变量这一步好妙啊。
对于这道题首先可以转化成这个柿子
\[\sum_{i=0}^3 a_i\cdot \sum_{j=0}^n [j\ \text{mod}\ 4=i]\cdot {\rm C}(n,j)\cdot s^j
\]
于是只要构造一个多项式 \(f\) 使得 \({\rm C}(n,i)\cdot s^i\) 为第 \(i\) 项的系数,且这个多项式的值可以快速计算,就可以用单位根反演以 \(\mathcal O(\)约数大小\()\) 的复杂度求出符合条件的系数和了。
令
\[f(x)=\sum_{i=0}^n {\rm C}(n,i)\cdot s^i\cdot x^i\cdot 1^{n-i}=(sx+1)^n
\]
还有一个问题,上面的系数和公式只计算了 \(i\ \text{mod}\ 4=0\),而我们还需要统计余数为 \(1,2,3\) 的情况。不难发现,只需要将多项式除以 \(x\)(自变量)的某次方即可化归为 \({\rm mod}\ 4=0\) 的问题。枚举余数 \(i\),对于每个 \(i\) 系数和就是
\[\frac{1}{4}\sum_{j=0}^{4-1}\frac{f(\omega_4^j)}{\omega_4^{ij\ \text{mod}\ 4}}
\]
时间复杂度 \(\mathcal O(16 T)\).
代码
#include <cstdio>
#define rep(i,_l,_r) for(register signed i=(_l),_end=(_r);i<=_end;++i)
#define fep(i,_l,_r) for(register signed i=(_l),_end=(_r);i>=_end;--i)
#define erep(i,u) for(signed i=head[u],v=to[i];i;i=nxt[i],v=to[i])
#define efep(i,u) for(signed i=Head[u],v=to[i];i;i=nxt[i],v=to[i])
#define print(x,y) write(x),putchar(y)
template <class T> inline T read(const T sample) {
T x=0; int f=1; char s;
while((s=getchar())>'9'||s<'0') if(s=='-') f=-1;
while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+(s^48),s=getchar();
return x*f;
}
template <class T> inline void write(const T x) {
if(x<0) return (void) (putchar('-'),write(-x));
if(x>9) write(x/10);
putchar(x%10^48);
}
template <class T> inline T Max(const T x,const T y) {if(x>y) return x; return y;}
template <class T> inline T Min(const T x,const T y) {if(x<y) return x; return y;}
template <class T> inline T fab(const T x) {return x>0?x:-x;}
template <class T> inline T gcd(const T x,const T y) {return y?gcd(y,x%y):x;}
template <class T> inline T lcm(const T x,const T y) {return x/gcd(x,y)*y;}
const int mod=998244353;
int s,a[5],w[5],ans,tmp,inv4,g;
long long n;
int qkpow(int x,long long y) {
int r=1;
while(y) {
if(y&1) r=1ll*r*x%mod;
x=1ll*x*x%mod; y>>=1;
}
return r;
}
int main() {
w[0]=1,g=qkpow(3,(mod-1)/4),inv4=qkpow(4,mod-2);
rep(i,1,3) w[i]=1ll*w[i-1]*g%mod;
for(int T=read(9);T-->0;) {
n=read(9ll),s=read(9); ans=0;
rep(i,0,3) a[i]=read(9);
rep(i,0,3) {
tmp=0;
rep(j,0,3) tmp=(tmp+1ll*qkpow((1ll*s*w[j]%mod+1)%mod,n)*qkpow(w[i*j%4],mod-2)%mod)%mod;
tmp=1ll*tmp*inv4%mod;
ans=(ans+1ll*a[i]*tmp%mod)%mod;
}
print(ans,'\n');
}
return 0;
}