您的位置:首页 > 其它

hoj 1560 - Factovisors

2008-02-04 00:38 435 查看
http://acm.hit.edu.cn/ojs/show.php?Proid=1560&Contestid=0

先处理一些特殊情况

m = 0 时一定不能整除 ;

n >= m 一定能整除;

其他情况做法如下:先对m分解质因数,并记录每个质因子和其个数,在判断n!是否含有这些质因子

下面说一下对m分解质因数的方法.首先生成一个素数表.因m为一个小于232的整型数,且232的平方根小于47000,所以我们的素数表只需求到47000即可,而小于47000的素数有4851个,因此素数表的大小应不小于4851.之后用素数表中的每一个素数试除m,求出m的每个质因子和其相应的个数.如果最后的商不等于1,那么这个商也是m的质因子,且它一定大于47000.

另外解题过程中需用到这个结论:对于任意的质数p, n!中有(n / p + n / p2 + n / p3 + … )个质因子p.

附代码

#include <iostream>
#include <cmath>
#include <queue>
#include <algorithm>
#include <functional>
#include <vector>

using namespace std;
int main()
{
int prime[4900] = {2, 3}, pn = 2, i, j, n, m, m0; int n0, a[4900], an[4900], anum;
long long sum;
bool divide;

for (i = 5; i <= 47000; i += 2)
{
for (j = 1; prime[j] * prime[j] < i; j++)
{
if (i % prime[j] == 0)
{
break;
}
}
if (i % prime[j] != 0)
{
prime[pn++] = i;
}
}

while (scanf("%d%d", &n, &m) == 2)
{
if (m == 0)
{
divide = false;
}
else if (n >= m)
{
divide = true;
}
else
{
m0 = m;
anum = 0;
memset(an, 0, sizeof(an));
for (i = 0; i < pn && prime[i] <= m; i++)
{
if (m0 % prime[i] == 0)
{
a[anum] = prime[i];
while (m0 % prime[i] == 0)
{
an[anum]++;
m0 /= prime[i];
}
anum++;
}
if (m0 == 1)
{
break;
}
}

if (m0 > 1)
{
a[anum] = m0;
an[anum++]++;
}

divide = true;
for (i = 0; i < anum; i++)
{
sum = 0;
if (a[i] > n)
{
divide = false;
break;
}
else
{
n0 = n;
while (n0 > 0)
{
sum += n0 / a[i];
n0 /= a[i];
if (sum >= an[i])
{
break;
}
}
if (sum < an[i])
{
divide = false;
break;
}
}
}

}

if (divide)
{
printf("%d divides %d!/n", m, n);
}
else
{
printf("%d does not divide %d!/n", m, n);
}
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: