题目:
Description
Robby is a clever boy, he can do multiplication very quickly, even in base-2 (binary system), base-16 (hexadecimal system) or base-100000. Now he wants to challenge your computer, the task is quite simple: Given a positive integer N, if we express the N ! (N ! = N * (N - 1) * (N - 2) * ... * 2 * 1) in base-B, how many ZEROs there will be at the end of the number. Can you make a wonderful program to beat him?Input
Each test case contain one line with two numbers N and B. (1 ≤ N ≤ 10^9, 2 ≤ B ≤ 100000) The input is terminated with N = B = 0.Output
Output one line for each test case, indicating the number of ZEROs.Sample Input
7 10 7 10000 7 2 0 0Sample Output
1 0 4
题目的意思就是,任给2个整数n、b,要求n!的b进制表示中有多少个后缀0
即求满足b^k整除n!的最大整数k
如果b是素数的话就非常简单,如果你不这么认为的话,请点击打开我的博客
我的这篇博客是另外1个题目,和这个有关系,下面这个重要的函数我又用了一次
long long degree_in_fact(long long m, int p) { if (m)return degree_in_fact(m / p, p) + m / p; return 0; }
本题b不是素数,但是原理的本质却是一样的。
把b进行唯一分解(不知道的请点击打开链接(算数基本定理))
比如b=224=2^5 * 7
那么b^k|n等价于2^(5*k)|n且7^k|n
所以k要么是degree_in_fact(n,2)/5要么是degree_in_fact(n,7),取其中较小的
有趣的是,但就b=224的情况来说,上面这2个谁大谁小还和n有关。
比如n为7的时候,degree_in_fact(7,2)/5=0,degree_in_fact(7,7)=1
当n为100的时候,degree_in_fact(100,2)/5=19,degree_in_fact(100,7)=16
至于一般的规律,我也没总结出来,但是应该都是像上面这样,只有2个都算出来才知道哪个更小。
写代码之前我做了预处理,知道了小于100000的素数有9592个。
然后又把代码改写成素数打表,对p数组进行初始化。
最后写本题代码,遍历p数组达到分解b的目的。
因为b最多有6个素因子,所以及时break可以提高一些效率。
代码:
#include<iostream> using namespace std; int p[9592]; bool isprime(int n) { for (int i = 2; i*i <= n; i++)if (n%i == 0)return false; return true; } long long degree_in_fact(long long m, int p) { if (m)return degree_in_fact(m / p, p) + m / p; return 0; } int main() { int k = 0; for (int i = 2; i < 100000; i++)if (isprime(i))p[k++] = i; int n, b; while (cin >> n >> b) { if (b == 0)break; int r = 1234567890; for (int i = 0; i < 9592; i++) { if (b%p[i])continue; int degree = 0; while (b%p[i] == 0) { b /= p[i]; degree++; } int t = degree_in_fact(n, p[i]) / degree; if (r>t)r = t; if (p[i] > b)break; } cout << r << endl; } return 0; }