前言
蒟蒻代码惨遭卡常,根本跑不过
前置芝士——单位根反演
单位根有这样的性质:
\[
\frac{1}{n}\sum_{i=0}^{n-1}\omega_{n}^{ki}=\left[n|k\right]
\]
所以可以得出单位根反演的式子
如果有\(f(x)=\sum_{i=0}a_ix^i\),就可以推出
\[
\sum_{i=0}^na_i\left[d|i\right]=\frac{1}{d}\sum_{p=0}^{d-1}f(\omega_d^p)
\]
证明可以把上面的式子代入,然后交换和号
思路
这道题要求的东西是这样的
\[
\sum_{i=0}^3a_i\sum_{j=0}^n\left(\begin{matrix}n\\j\end{matrix}\right)s^j\left[j\%4=i\right]
\]
写出\(\sum_{j=0}^n\left(\begin{matrix}n\\j\end{matrix}\right)s^j\)的生成函数,由二项式定理得到是\((sx+1)^n\)
不妨设i=0
则要求
\[
\sum_{j=0}^n\left(\begin{matrix}n\\j\end{matrix}\right)s^j\left[4|j\right]
\]
直接套公式
原式等于
\[
\frac{1}{4}\sum_{p=0}^3f(\omega_4^p)
\]
对于i等于1,2,3,相当于原式向右边“移动”了1,2,3个位置
乘以自变量的对应倍即可
代码
蒟蒻的代码不知道为什么跑的辣么慢,只有60pts
#include <cstdio> #include <algorithm> #include <cstring> #define int long long using namespace std; int T,a[4],s,n,MOD=998244353,W[5]={1,911660635,998244352,86583718},inv=748683265; int pow(int a,int b){ int ans=1; while(b){ if(b&1) ans=(ans*a)%MOD; a=(a*a)%MOD; b>>=1; } return ans; } signed main(){ scanf("%lld",&T); while(T--){ scanf("%lld %lld %lld %lld %lld %lld",&n,&s,&a[0],&a[1],&a[2],&a[3]); int ans=0; for(int i=0;i<4;i++){ int mid=0; for(int j=0;j<4;j++) mid=(mid+pow((s*W[j]%MOD+1%MOD)%MOD,n)*pow(W[i*j%4],MOD-2)%MOD)%MOD; ans=(ans+a[i]*mid%MOD*inv%MOD)%MOD; } printf("%lld\n",ans); } return 0; }
来源:https://www.cnblogs.com/dreagonm/p/10447974.html