UVA 10061

来源:互联网 发布:win10网络不可用红叉 编辑:程序博客网 时间:2024/06/17 07:15

题目大意:输入n,m。求n!在m进制中末尾有几个零,以及为几位数。

解题思路:林炜大佬打得代码。。。漂亮。n!在m进制有几位,卡精度,用斯特林公式wa了。用对数求,加上1e-9才过。对数求法是这样的。。。设结果为X位数,那么n!< m^X。所以X = logm(n!) = logm (2) + ...logm(n)。而末尾0的求法,是求出m的质因数,然后算2~n,能被不同的m质因数整除的为质因数的几倍,取最少的,则为末尾的0。例如:5 16。16 = 2 * 2 * 2 * 2。2~5只有2、4可以被2整除,一共3个2。要求4个2才能一个0。所以末尾没有0。

ac代码:

#include <iostream>#include <cmath>#include <cstring>using namespace std;int n, k, cnt, num, m;int vis[2000005], mark[2000005];double zero;int main(){while (scanf("%d%d", &n, &k)!=EOF){memset(vis, 0, sizeof(vis));memset(mark, 0, sizeof(mark));zero = 0; if ( !n || n == 1)zero = 1;else{for (int i = 2; i <= n; i++)zero += log(i);zero  = floor( zero/log(k) + 1e-9 ) + 1; }m = k;for(int i = 2; i <= k; i++)while(k%i==0){vis[i]++;k /= i;}for(int i = 2; i <= n; i++){int d =sqrt(i);int s = i;for(int j = 2; j <= d; j++)while(s % j==0){mark[j]++;s/=j;}mark[s]++;}int cnt = 99999999;for(int i = 1; i <= m; i++)if(vis[i])cnt = min(mark[i]/vis[i],cnt);printf("%d %.0lf\n", cnt, zero);}return 0;}

大佬手打质数表,存一份:

for(int i = 2; i <= 800; i++)if(!p[i]){p[++p[0]] = i;for(int j = 2*i; j <= 800; j+=i)p[j] = 1;}
原创粉丝点击