天天看點

uva 10061 - How many zero's and how many digits ?

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