SCU - 2763 Factorial(任意阶乘中任意数的次数)

题目:

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 0

Sample 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;
}
时间: 2024-10-12 22:49:14

SCU - 2763 Factorial(任意阶乘中任意数的次数)的相关文章

在O(n)时间复杂度内求无序数组中任意两个元素的最大差值,以及存在的组数

题目描述: 求无序数组中任意两个元素的最大差值,以及存在最大差值的组别数. 输入: 输入包含两行,第一行输入一个整数n:第二行n个正整数,用空格隔开. 输出: 输出为一行,包含最大差值,以及存在组别数. 样例输入: 4 4  1  2  1 输出: 3  2 一种实现代码如下(Java版): 1 import java.util.Scanner; 2 /** 3 * 在O(n)时间复杂度内求无序数组中任意两个元素的最大差值,以及存在的组数 4 * @author JiaJoa 5 * 6 */

从1到非负整数n中1出现的次数 求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数? 为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次, 但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化, 可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。

/*从1到非负整数n中1出现的次数求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1.10.11.12.13因此共出现6次,但是对于后面问题他就没辙了.ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数). */ import java.util.*; public class Class36 { public int NumberOf1Between1A

hdu4612 无向图中任意添加一条边后使桥的数量最少 / 无向图缩点+求树的直径

题意如上,含有重边(重边的话,俩个点就可以构成了边双连通). 先缩点成树,在求数的直径,最远的连起来,剩下边(桥)的自然最少.这里学习了树的直径求法:第一次选任意起点U,进行bfs,到达最远的一个点v(level最深)该点必然是树的直径的一个端点,,再从该点出发,bfs,到最深的一点,该点深度就是直径.(证明:先假设u,是直径上一点,S,T是直径的端点,设v!=t,则有(V,U)+(U,S)>(T,U)+(U,S),矛盾,故t=v:若u不是直径上一点,设u到直径上的一点为x,同理易证. 最后 缩

(笔试题)数组A中任意两个相邻元素大小相差1,在其中查找某个数。

题目: 数组A中任意两个相邻元素大小相差1,现给定这样的数组A和目标整数t,找出t在数组A中的位置.如数组:[1,2,3,4,3,4,5,6,5],找到4在数组中的位置. 思路: 很明显,在数组中寻找某个数的复杂度为O(n),但在某些特殊数组中,可以通过寻找规律来减少比较次数. 上述数组的规律就是:相邻元素相差1,奇偶交替排列. 如果某个数A[i]等于要查找的数x,那么由于奇偶交替排列的关系,可以跳过下个数A[i+1],即i=i+2: 如果某个数A[i]不等于要查找的数x,那么由于相邻元素相差1

二叉树中任意两节点的最低共同父节点

通过两个和二叉树相关的算法题来看看和递归在二叉树中的应用 输入二叉树中的两个结点,输出这两个结点在数中最低的共同父结点. 思路: 如果这两个节点不在同一个子树下面,那么这棵树的根节点就是他们的共同最低父节点. 如果两个都在右子树,那么以右子树的最上面的那个节点作为根节点,重新进行判断,递归调用. 同理两个都在左子树,则方法同上.  也就是说,最终的结果分别只有三种情况,一个节点在右子树,一个节点在左子树.两个节点都在右子树,两个节点都在左子树. 如果是第一种情况,那么当前的节点就是他们最低的公共

例6.13 已知一个一维数组a[1..n](n&lt;25),又已知一整数m。 如能使数组a中任意几个

/*例6.13 已知一个一维数组a1..n,又已知一整数m. 如能使数组a中任意几个元素之和等于m,则输出YES,反之则为NO.[分析]对于一个已确定的数组a[1..n]和一个确定的数m,判断能否使数组a中任意几个元素之和等于m,等价于判断能否从数组a中取任意数使其和为m. 对于a中任意元素a[n]只有取与不取两种情况: (1)取a[n]: 则此时问题转化为:对于一个已确定的数组a[1..n-1]和一个确定的数m-a[n],判断能否使数组a[1..n-1]中任意几个元素之和等于m-a[n]. (

求二叉树中任意两个结点的距离

求二叉树中任意两个结点的距离 实现步骤: 计算跟到第一个结点的距离: 计算跟到第二个结点的距离: 计算lca: 计算跟到lca结点的距离: 结果为(1) + (2) - 2 * (4),因为重复计算了两次的从跟到lca结点的距离: 1 class Node(object): def __init__(self, value=0): self.value = value self.left = self.right = None def get_path_length(root, n, path)

[经典面试题][百度]数组A中任意两个相邻元素大小相差1,在其中查找某个数。

题目 数组A中任意两个相邻元素大小相差1,现给定这样的数组A和目标整数t,找出t在数组A中的位置.如数组:[1,2,3,4,3,4,5,6,5],找到4在数组中的位置. 思路 这道题目最差时间复杂度也是O(N),所以重点在于能不能找到一种尽可能减少比较次数的方法. 如数组:[1,2,3,4,3,4,5,6,5],找到4在数组中的位置.4和1比较,差为3,那么即使最好情况(递增或者递减),4也就是在a[3]的位置,可以跳过a[1]a[2].这样在特定数组(目标值和a[1]相差很大)的情况下或许可以

关于java中任意对象强制转换为接口类型的问题

java中任意对象强转为接口类型都不会有编译错误 public class Apple implements Eatable{ public static void main(String args[]) { Drinkable drinkable = (Drinkable)new Apple(); } } interface Eatable{} interface Drinkable{} java中的类可以多实现接口,Java编译器无法判断该类是否实现了该接口所以不会有编译错误. 但是Java