Codeforces 582D. Number of Binominal Coefficients 题解

题目链接:D. Number of Binominal Coefficients

题目大意:洛谷


题解:首先根据库默尔定理,可以得知(inom{a+b}{a})就是(p)进制下的(a+b)的进位次数,所以可以用数位 DP 解决,设置的状态是(f_{i,j,0/1,0/1})表示前(i)个数,进位(j)次,当前是否等于上届,当前是否有来自下一位的进位,然后非常非常麻烦的转移(花了我一个下午),然后就结束了。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
void read(int &a){
	a=0;
	char c=getchar();
	while(c<'0'||c>'9'){
		c=getchar();
	}
	while(c>='0'&&c<='9'){
		a=(a<<1)+(a<<3)+(c^48);
		c=getchar();
	}
}
typedef long long ll;
const int Maxn=10000;
const int Mod=1000000007;
int p,q,n,m,len;
int a[Maxn+5];
int b[Maxn+5];
char s[Maxn+5];
int f[2][Maxn+5][2][2];
int div(int x){
	ll num=0;
	len=0;
	for(int i=1;i<=m;i++){
		num=num*10+a[i];
		if(len>0||num>=x){
			a[++len]=num/x;
		}
		num%=x;
	}
	for(int i=len+1;i<=m;i++){
		a[i]=0;
	}
	m=len;
	return num;
}
int main(){
	read(p),read(q);
	scanf("%s",s+1);
	while(s[++m]!='');
	m--;
	for(int i=1;i<=m;i++){
		a[i]=s[i]-'0';
	}
	while(m){
		b[++n]=div(p);
	}
	for(int i=1;i<=n;i++){
		a[i]=b[n-i+1];
	}
	if(n==0){
		puts("0");
		return 0;
	}
	f[0][0][1][0]=1;
	for(int i=1;i<=n;i++){
		int tmp_0=1ll*p*(p+1)/2%Mod,tmp_1=1ll*p*(p-1)/2%Mod,tmp_2=1ll*a[i]*(a[i]+1)/2%Mod,tmp_3=1ll*a[i]*(a[i]-1)/2%Mod,tmp_4=1ll*a[i]*(p+p-a[i]-1)/2%Mod,tmp_5=1ll*a[i]*(p+p-a[i]+1)/2%Mod;
		memset(f[1],0,sizeof f[1]);
		for(int j=0;j<i;j++){
			f[1][j][0][0]=(f[1][j][0][0]+1ll*f[0][j][0][0]*tmp_0+1ll*f[0][j][1][0]*tmp_2)%Mod;
			f[1][j][0][1]=(f[1][j][0][1]+1ll*f[0][j][0][0]*tmp_1+1ll*f[0][j][1][0]*tmp_3)%Mod;
			f[1][j][1][0]=(f[1][j][1][0]+1ll*f[0][j][1][0]*(a[i]+1))%Mod;
			f[1][j][1][1]=(f[1][j][1][1]+1ll*f[0][j][1][0]*a[i])%Mod;
			f[1][j+1][0][0]=(f[1][j+1][0][0]+1ll*f[0][j][0][1]*tmp_1+1ll*f[0][j][1][1]*tmp_4)%Mod;
			f[1][j+1][0][1]=(f[1][j+1][0][1]+1ll*f[0][j][0][1]*tmp_0+1ll*f[0][j][1][1]*tmp_5)%Mod;
			f[1][j+1][1][0]=(f[1][j+1][1][0]+1ll*f[0][j][1][1]*(p-a[i]-1))%Mod;
			f[1][j+1][1][1]=(f[1][j+1][1][1]+1ll*f[0][j][1][1]*(p-a[i]))%Mod;
		}
		swap(f[0],f[1]);
	}
	int ans=0;
	for(int i=q;i<=n;i++){
		ans=(ans+f[0][i][0][0])%Mod;
		ans=(ans+f[0][i][1][0])%Mod;
	}
	printf("%d
",ans);
	return 0;
}
原文地址:https://www.cnblogs.com/withhope/p/13602723.html