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;
}
posted @ 2020-08-08 22:49  gmh77  阅读(311)  评论(0编辑  收藏  举报