题目

传送门

解法

算是单位根反演的经典应用吧。先讲一个柿子

\[[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;
}
posted on 2021-02-17 17:18  Oxide  阅读(66)  评论(0)    收藏  举报