[2019.2.24]BZOJ4591 [Shoi2015]超能粒子炮·改

以下除法一律为整除。

(sum_{i=0}^kC_n^i mod p,p=2333)

(f(i,j)=sum_{k=0}^jC_i^k)

(f(n,k)=sum_{i=0}^kC_n^i)

(kle p,nle p),预处理(0le ile p,0le jle i)(C_i^j)及其前缀和。

否则

(f(n,k))

(=sum_{i=0}^kC_{n mod p}^{i mod p} imes C_{n/p}^{i/p})

(=sum_{b=0}^{k/p-1}sum_{i=0}^{p-1}(C_{n mod p}^i imes C_{n/p}^{b})+C_{n/p}^{k/p} imes(sum_{i=0}^{k mod p}C_{n mod p}^i))

(=sum_{b=0}^{k/p-1}C_{n/p}^{b} imessum_{i=0}^{p-1}C_{n mod p}^i+C_{n/p}^{k/p} imes(sum_{i=0}^{k mod p}C_{n mod p}^i))

(=f(n/p,k/p-1) imes sum_{i=0}^{p-1}C_{n mod p}^i+C_{n/p}^{k/p} imes f(n mod p,k mod p))

(f(n/p,k/p-1))递归,(sum_{i=0}^{p-1}C_{n mod p}^i)预处理过了,(C_{n/p}^{k/p})直接lucas定理,(f(n mod p,k mod p))也预处理过了。

code:

#include<bits/stdc++.h>
using namespace std;
const long long p=2333;
int T,C[p+10][p+10],sum[p+10][p+10];
long long n,k;
int Lucas(long long x,long long y){//C_x^y
	if(y>x)return 0;
	if(x<=p&&y<=p)return C[x][y];
	return Lucas(x/p,y/p)*C[x%p][y%p]%p;
}
int F(long long x,long long y){
	if(y>x)y=x;
	if(!y)return 1;
	if(y<0)return 0;
	if(x<=p&&y<=p)return sum[x][y];
	return (F(x/p,y/p-1)*sum[x%p][p-1]%p+Lucas(x/p,y/p)*sum[x%p][y%p]%p)%p;
}
int main(){
	C[0][0]=sum[0][0]=1;
	for(int i=1;i<=p;++i)for(int j=0;j<=i;++j)C[i][j]=(C[i-1][j]+(j?C[i-1][j-1]:0))%p;
	for(int i=0;i<=p;++i)for(int j=0;j<=p;++j)sum[i][j]=((j?sum[i][j-1]:0)+C[i][j])%p;
	scanf("%d",&T);
	while(T--)scanf("%lld%lld",&n,&k),printf("%d
",F(n,k));
	return 0;
}
原文地址:https://www.cnblogs.com/xryjr233/p/BZOJ4591.html