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;
}
posted @ 2022-01-11 21:42  Point_King  阅读(35)  评论(0编辑  收藏  举报