首页 > 代码库 > UVa 10139 - Factovisors

UVa 10139 - Factovisors

题目:判断n!能否整除m。

分析:数论。先将m拆成素数的积的形式,再判断n!中对应每个素数的个数,是否大于m的即可。

            首先,打表计算50000内素数,用这些素数除不尽的数一定也是素数,不过最多只有一个;

            然后,分解m成素数的积的形式,统计每个素数因子的个数;

            最后,判断n!中每个素数因子的个数是否大于m中对应的素数个数;

                        设f(n,p)为n!中素数p的个数,则有f(n,p)= f(n/p,p)+ n/p;

            { 能被p整除的数为:p,2p,3p,..,p^2,p(p+1),..,p^3,..,p^k ≤ n < p^(k+1);

              共有,n/p个,全部除以p则剩余的含有p因数的数字有,p,2p,..,p^2,..,p^3,..,p^(k-1);

              因此有f(n,p)= f(n/p,p)+ n/p ,n < p 时 f(n,p)= 0 }

说明:最近忙着最实验,有几天没有刷题了╮(╯▽╰)╭。

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>

using namespace std;

int prime[50000];
int used[50000];
int p[50],k[50];

int size(int n, int p)
{
	if (n < p) return 0;
	return size(n/p, p) + n/p;
}

int main()
{
	memset(used, 0, sizeof(used));
	int count = 0;
	for (int i = 2 ; i < 50000 ; ++ i)
		if (!used[i]) {
			used[i] = 1;
			prime[count ++] = i;
			for (int j = 2*i ; j < 50000 ; j += i)
				used[j] = 1;
		}
		
	int n,m;
	while (~scanf("%d%d",&n,&m)) {
		int move = 0,save = 0,t = m;
		memset(k, 0, sizeof(k));
		while (t > 1 && move < count) {
			while (t%prime[move] == 0) {
				t /= prime[move];
				k[save] ++;
			}
			if (k[save]) p[save ++] = prime[move];
			move ++;
		}
		if (t > 1) {
			p[save] = t;
			k[save] = 1;
			save ++;
		}
		
		int flag = 1;
		for (int i = 0 ; i < save ; ++ i) 
			if (size(n, p[i]) < k[i]) {
				flag = 0;
				break;
			}
		
		if (flag && m)
			printf("%d divides %d!\n",m,n);
		else printf("%d does not divide %d!\n",m,n);
	}
	
	return 0;
}


UVa 10139 - Factovisors