LOJ6485 LJJ学二项式定理
单位根反演
单位根反演是拿来做\([k\bmod m=0,1,\dots,m-1]\)这样的余数条件判别式的一种展开方法。
这类题通常\(m\)很小,可以枚举,并且模数具有\(m\)次单位根。
单位根反演主要运用的是如下的等式(快速傅里叶变换的理论的一部分)
分类讨论证明:
-
\(k\bmod m=0\),那么\(\omega_m^k=1\),变成简单加法。
\[\frac{1}{m}\sum_{i=0}^{m-1}(\omega_m^k)^i=\frac{1}{m}\sum_{i=0}^{m-1}1^i=1 \] -
\(k\bmod m\neq 0\),那么\(\omega_m^k\neq 1\),变成等比数列求和。
\[\frac{1}{m}\sum_{i=0}^{m-1}(\omega_m^k)^i=\frac{1}{m}\frac{\omega_m^0-(\omega_m^k)^m}{1-\omega_m^k}=0 \]
令\(F(x)=\sum_{i=0}^nf_ix^i\),现在我们要求\(\sum_{i=0}^nf_i[i\bmod m=0]\),那么考虑如下计算式
那么对于一般情况,如果我们要求\(\sum_{i=0}^nf_i[i\bmod m=a]\)又该怎么做呢?对\(\frac{F(x)}{x^a}\)做相同的事情即可。
LJJ学二项式定理
LJJ学完了二项式定理,发现这太简单了,于是他将二项式定理等号右边的式子修改了一下,代入了一定的值,并算出了答案。
但人口算毕竟会失误,他请来了你,让你求出这个答案来验证一下。
一共有\(T\)组数据,每组数据如下:
输入以下变量的值:\(n, s, a_0, a_1, a_2, a_3\),求以下式子的值:
对于\(100\%\)的数据,\(1 \leq T \leq 10^5, 1 \leq n \leq 10 ^ {18}, 1 \leq s, a_0, a_1, a_2, a_3 \leq 10^{8}\)。
题解
令\(F(x)=\sum_{i=0}^n\binom{n}{i}s^ix^i=(sx+1)^n\),然后单位根反演即可。
这破题还卡常……必须要预处理,不然会有16倍的常数。
array<int,4> w,iw;
void real_main(){
int n=read<int64>()%(mod-1),s=read<int>();
function<int(int)> F=[&](int x)->int{
return fpow(mul(s,x)+1,n);
};
array<int,4> a,f;
for(int i=0;i<4;++i){
read(a[i]);
f[i]=F(w[i]);
}
int ans=0;
for(int j=0;j<4;++j)for(int i=0;i<4;++i)
ans=add(ans,mul(a[j],mul(f[i],fpow(iw[i],j))));
ans=mul(ans,fpow(4,mod-2));
printf("%d\n",ans);
}
int main(){
for(int i=0;i<4;++i){
w[i]=fpow(3,(mod-1)/4*i);
iw[i]=fpow(w[i],mod-2);
}
for(int T=read<int>();T--;) real_main();
return 0;
}