6170. 【GDSOI 2019 day2】高中生数学题(库默尔定理)
题目描述
k ≥ 1,1 < p^k ≤ n ≤ 10^18 .
题解
库默尔定理:\(\binom{n+m}{n}\)的质因子p的次数为n+m在p进制下的进位次数
证明:次数=\(\sum_{i>=1}(n+m)/p^i-n/p^i-m/p^i\)
等于去掉前i位后考虑,发现只有n+m在第i+1位有进位才会为1否则为0
对于本题就是i+(n-i)的进位次数,因为a+b=c的进位次数等于c-b=a(感受一下,本质都是在某一位加/减p),直接数位dp维护连续0个数以及因子个数即可
由于p可能很大所以要直接算
code
#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define ll long long
#define file
using namespace std;
ll f[64][64][64][2],a[64],n,p,K,ans;
int i,j,k,l,t;
int main()
{
freopen("math.in","r",stdin);
#ifdef file
freopen("math.out","w",stdout);
#endif
scanf("%lld%lld%lld",&n,&p,&K);
while (n) a[++t]=n%p,n/=p;
f[t][0][0][0]=1;
fd(i,t,1)
{
fo(j,0,t)
{
fo(k,0,t)
{
fo(l,0,1)
if (f[i][j][k][l])
{
if (!l)
{
f[i-1][j+1][k][l]+=f[i][j][k][l];
f[i-1][0][k][1]+=f[i][j][k][l]*a[i];
}
else
{
f[i-1][j+1][k][l]+=f[i][j][k][l];
f[i-1][0][k][l]+=f[i][j][k][l]*a[i];
f[i-1][0][k+j+1][l]+=f[i][j][k][l]*((p-1)-a[i]);
}
}
}
}
}
fo(j,0,t)
{
fo(k,K,t)
{
fo(l,0,1)
ans+=f[0][j][k][l];
}
}
printf("%lld\n",ans);
fclose(stdin);
fclose(stdout);
return 0;
}