P3746 [六省聯考 2017] 組合數問題
阿新 • • 發佈:2022-01-12
求
\[(\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; }