P3746 [六省联考 2017] 组合数问题
求
\[(\sum_{i=0}^\infty\binom{nk}{ik+r})\bmod p
\]
其中 \(0\le r<k\le 50,1\le n\le10^9\) 。
\[\text{res}=\sum_{i\equiv r\pmod k}\binom{nk}{i}\\
=\sum_{i\equiv r\pmod k}[x^i](1+x)^{nk}\\
\]
好像可以单位根反演,
\[\text{res}=\sum_{i=0}^{k-1}\frac{(1+\omega_k^i)^{nk}}{\omega_k^{ir}}
\]
但是 \(k\) 不固定,\(p\) 也不固定且非质数,不太好搞(凉凉)。
但是!单位根反演和循环卷积是存在一定的关系的,我们考虑单位根反演实际上求得就是循环卷积在某一位上的系数,我们考虑到这里暴力做循环卷积是可行的,所以直接做即可。
#include<bits/stdc++.h>
using namespace std;
const int K=50;int MOD;
int ADD(int x,int y){return x+y>=MOD?x+y-MOD:x+y;}
int TIME(int x,int y){return (int)(1ll*x*y%MOD);}
long long n;int k,r;
struct Polynomial{int f[K];int &operator [] (int x){return f[x];}}f;
Polynomial operator * (Polynomial a,Polynomial b){
Polynomial res={};
for(int i=0;i<k;++i){
for(int j=0;j<k;++j)
res[(i+j)%k]=ADD(res[(i+j)%k],TIME(a[i],b[j]));
}
return res;
}
Polynomial operator ^ (Polynomial x,long long k){
Polynomial res={1};
for(;k;k>>=1,x=x*x) if(k&1) res=res*x;
return res;
}
int main(){
cin>>n>>MOD>>k>>r;
f[0%k]++,f[1%k]++,f=(f^(n*k));
return printf("%d\n",f[r]),0;
}