给定一个质数p和整数α,A。请计算有多少对(n,k)满足0≤k≤n≤A 且 (nk)(nk) 是 pαpα 的倍数。
答案比较大,对 109+7109+7 取余再输出。
(nk)(nk) 的意思是从n个东西中选k个的方法数。
样例解释:
在这个样例中,能被4整除的是 (41)=4(41)=4 , (43)=4(43)=4 和 (63)=20(63)=20 。
输入
单组测试数据。 第一行有两个整数 p 和α (1≤p,α≤10^9, p 是质数)。 第二行有一个整数A (0≤A<10^1000),不含前导0。
输出
输出答案占一行。
输入样例
样例输入1 2 2 7
输出样例
样例输出1 3
知道kummer定理后直接数位dp就好了。
设f[i,j,0/1,0/1]表示有多少个数对(x,y)从高到低做到第i位,进位了j次,x+y的前i位是否卡着A的上界,下一位是否必须要进位。
直接转移即可。
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
using std::cerr;
cs int mod=1e9+7,inv2=mod+1>>1;
inline int add(int a,int b){return (a+=b)>=mod?a-mod:a;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline int mul(int a,int b){ll r=(ll)a*b;return r>=mod?r%mod:r;}
inline void Inc(int &a,int b){(a+=b)>=mod&&(a-=mod);}
inline void Dec(int &a,int b){(a-=b)<0&&(a+=mod);}
inline int c2(int n){return mul(mul(n,n-1),inv2);}
cs int N=3.5e3+5;
char s[N];
ll c[N],b[N];
int f[N][N][2][2];
int p,q;
inline void work(){
ll x=0;
for(int re i=1;i<=c[0];++i){
c[i]+=x*10;
x=c[i]%p,c[i]/=p;
}
int j=1;b[++b[0]]=x;
while(j<=c[0]&&!c[j])++j;
if(j>c[0])c[0]=0;
else {
for(int re i=j;i<=c[0];++i)c[i-j+1]=c[i];
c[0]-=j-1;
}
}
signed main(){
#ifdef zxyoi
freopen("binom.in","r",stdin);
#endif
scanf("%d%d",&p,&q);
scanf("%s",s+1);c[0]=strlen(s+1);
for(int re i=1;i<=c[0];++i)c[i]=s[i]^48;
while(c[0])work();
if(q>b[0])std::cout<<"0\n",exit(0);
f[b[0]+1][0][0][1]=1;int cp1=c2(p+1),cp0=c2(p);
for(int re i=b[0];i;--i){
int x=b[i];
int x1=c2(x+1),x0=c2(x),px=mul(p,x);
for(int re j=0;j<=b[0]-i;++j){
if(f[i+1][j][0][0]){
int v=f[i+1][j][0][0];
Inc(f[i][j][0][0],mul(v,cp1));
Inc(f[i][j+1][1][0],mul(v,cp0));
}
if(f[i+1][j][1][0]){
int v=f[i+1][j][1][0];
Inc(f[i][j][0][0],mul(v,cp0));
Inc(f[i][j+1][1][0],mul(v,cp1));
}
if(f[i+1][j][0][1]){
int v=f[i+1][j][0][1];
Inc(f[i][j][0][0],mul(v,x1));
Inc(f[i][j][0][1],mul(v,x+1));
Inc(f[i][j+1][1][0],mul(v,x0));
Inc(f[i][j+1][1][1],mul(v,x));
}
if(f[i+1][j][1][1]){
int v=f[i+1][j][1][1];
Inc(f[i][j][0][0],mul(v,dec(px,x1)));
Inc(f[i][j][0][1],mul(v,p-x-1));
Inc(f[i][j+1][1][0],mul(v,dec(px,x0)));
Inc(f[i][j+1][1][1],mul(v,p-x));
}
}
}
int ans=0;
for(int re i=q;i<=b[0];++i)Inc(ans,add(f[1][i][0][1],f[1][i][0][0]));
std::cout<<ans<<"\n";
return 0;
}