题目传送门
分析:
给出\(N\)和\(K\),求:
\[\sum_{i=0}^{n}[k|i]\binom{n}{i} \]
想一下\([k|i]\)怎么表达
开始离谱的构造
找到\(k\)次单位根\(w_k=g^{\frac{p-1}{k}}\)
发现:
\[\sum_{j=0}^{k-1}w_k^{ij}=[k|i]k \]
当\(k|i\)时,\(w_k^i=1\),显然成立
否则等比数列求和,\(\sum_{j=0}^{k-1}w_k^{ij}=\frac{1-w_k^{ik}}{1-w_k^i}=0\),也成立
好离谱的构造2333
开始推式子:
\[\sum_{i=0}^{n}[k|i]\binom{n}{i} \]
\[=\sum_{i=0}^{n}\frac{1}{k}\sum_{j=0}^{k-1}w_k^{ij}\binom{n}{i} \]
\[=\frac{1}{k}\sum_{j=0}^{k-1}\sum_{i=0}^{n}w_k^{ij}\binom{n}{i} \]
\[=\frac{1}{k}\sum_{j=0}^{k-1}(w_k^j+1)^n \]
(二项式定理)
直接算,复杂度\(O(klogn)\)
#include
#include
#include
#include
#define maxn 2000005
#define MOD 998244353
using namespace std;
inline long long getint()
{
long long num=0,flag=1;char c;
while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
return num*flag;
}
int n,k;
inline int ksm(int num,int k)
{
int ret=1;
for(;k;k>>=1,num=1ll*num*num%MOD)if(k&1)ret=1ll*ret*num%MOD;
return ret;
}
int main()
{
n=getint()%(MOD-1),k=getint();
int ans=0;
int wn=ksm(3,(MOD-1)/k),w=ksm(3,(MOD-1)/k);
for(int i=0;i