题意:给你一个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; }