LOJ

题目

传送门

解法

算是单位根反演的经典应用吧。

首先知道有一个求多项式特定倍数的系数和公式((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;
}
原文地址:https://www.cnblogs.com/AWhiteWall/p/14409246.html