题意:给你一个N和一个进制B,求N!在B进制下末尾0的个数和总的位数。
第一个问题很容易转化为求N!能整除几个B,这里可以处理出所有B的素因子和素因子的个数a[i],然后同样对N!处理出所有整除B的各个素因子的个数pnum[i],对于所有的pnum[i] / a[i]取最小值即可。
求总的位数有两种求法,一种是直接用double的 cal来保存N!当前的值,枚举过程中只要cal >=B就除一次。
第二种是用log函数来求,由1*2*3 .... *N = B^x,两边同取log得 log1 + log2 +log3 .,.. + log N = log (B^x) = x* log(B),求出来的x要+1,不过这里居然被坑了精度误差。。。最后的需要 (int)(x+0.00005)+1 ,坑了,没经验,下次要注意!
#include <stdio.h>
#include <string.h>
#include <math.h>
#define LL long long
int a[1111], pri[1111], pnum[1111];
void init() {
memset(a, 0, sizeof(a));
memset(pnum, 0, sizeof(pnum));
}
int main () {
int n, b, i, j;
while(scanf("%d%d", &n, &b) != -1) {
init();
double ans2 = 0;
for(i = 1;i <= n; i++)
ans2 += log((double)i);
ans2 = ans2/log((double)b);
int num = 0;
for(i = 2;i*i <= b; i++) {
if(b%i == 0) {
while(b%i == 0)
a[num]++ , b /= i;
pri[num++] = i;
}
}
if(b != 1) {
pri[num] = b;
a[num++] = 1;
}
for(i = 1;i <= n; i++) {
LL cur = i;
for(j = 0;j < num; j++) {
while(cur%pri[j] == 0) {
pnum[j]++, cur /= pri[j];
}
}
}
LL ans1 = pnum[0]/a[0];
for(i = 1;i < num; i++) {
if(ans1 > pnum[i]/a[i])
ans1 = pnum[i]/a[i];
}
printf("%lld %d\n", ans1, (int)(ans2+0.000005)+1);
}
return 0;
}