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;
}

你可能感兴趣的:(uva 10061 - How many zero's and how many digits ?)