題意:給你一個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;
}