题目
解法
算是单位根反演的经典应用吧。
首先知道有一个求多项式特定倍数的系数和公式((k) 倍):
[sum_{i=0}^{frac{n}{k}}[x^{ik}]f(x)=frac{1}{k}sum_{i=0}^{k-1}f(omega_k^i)
]
对于这道题可以转化成这个柿子:
[sum_{i=0}^3 a_isum_{j=0}^n [j ext{mod} 4=i] imes C(n,j) imes s^j
]
这样我们构造一个多项式 (f) 使得 (C(n,i) imes s^i) 为第 (i) 项的系数就可以用单位根反演快速求出符合条件的系数和了。
令
[f(x)=sum_{i=0}^n C(n,i) imes s^i imes x^i imes 1^{n-i}
]
[=(sx+1)^n
]
还有一个问题,上面的系数和公式只计算 (i ext{mod} 4=0),而我们还需要统计余数为 (1,2,3) 的情况。
不过我们发现,多项式 (g(x)=sum_{i=0}^n a_ix^i) 如果整体除掉一个 (x) 即为 (g(x)div x=sum_{i=1}^n a_ix^{i-1})。容易发现这相当于系数整体往左移了一位,那么原先 ( ext{mod} 4=1) 的系数现在 ( ext{mod} 4=0),就可以计算了。
具体就是枚举余数 (i),对于每个 (i) 系数和就是
[frac{1}{4}sum_{j=0}^{4-1}frac{f(omega_4^j)}{omega_4^{ij ext{mod} 4}}
]
时间复杂度 (mathcal O(16 imes 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,'
');
}
return 0;
}