题意: 判断n!能否整除m,n,m的大小范围为 2^32 差不多是10^10的大小吧;
思路:
先对m拆分成素数,然后再判断n!包括的素数的个数是否都大于或等于m的素数的个数,如果是的话就能整除,否则不能整除;
判断n!中素数p的个数的公式为 k = n / p + n / (n ^ 2) + n / (p ^3) + ……+……;各个数都是整除;
然后打表的话就是打10^5的素数表,去一半,然后如果在素数表里面都找不到能够整除的素数的话就说明这个数就是素数;
还说一点,这个题应该是vua上面的数据比较坑一点,一直wa,但是在poj过了,不知道到底是哪个数据错了,如果大家知道,希望大家跟我说一下,万分感谢!!!
模板:
int get_num(ll n,ll p)
{
int ans = 0;
while(n)
{
ans += n / p;
n /= p;
}
return ans;
}
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn = 100000 + 10;
bool is_prime[maxn];
ll prime[maxn];
ll len;
void Init()
{
memset(is_prime,true,sizeof(is_prime));
is_prime[0] = is_prime[1] = false;
for(int i = 2;i < maxn ; i ++)
{
if(is_prime[i])
{
for(int j = i * 2; j < maxn ; j += i)
{
is_prime[j] = false;
}
}
}
len = 0;
for(int i = 2; i < maxn ;i ++)
{
if(is_prime[i])
{
prime[len ++] = i;
}
}
}
struct Node
{
int data;
int times;
}a[maxn / 10];
int main()
{
Init();
ll n,m;
while( ~ scanf("%I64d%I64d",&n,&m) )
{
memset(a,0,sizeof(a));
int lens = 0;
ll t = m;
for(int i = 0 ; i < len ; i ++)
{
while(t % prime[i] == 0 && t != 1 && prime[i] <= m)
{
a[lens].data = prime[i];
a[lens].times ++;
t /= prime[i];
if(t % prime[i] )
lens ++;
}
if(t == 1 || prime[i] > m)
break;
}
if( m == 0)
{
cout << m<< " does not divide " << n << "!"<< endl;
continue;
}
if(m == 1)
{
cout << m <<" divides "<< n <<"!" << endl;
continue;
}
if(n >= m)
{
cout << m <<" divides "<< n <<"!" << endl;
continue;
}
if(lens == 0)
{
if(n >= m)
{
cout << m <<" divides "<< n <<"!" << endl;
}
else cout << m<< " does not divide " << n << "!"<< endl;
continue;
}
bool flag = true;
for(int i = 0 ; i < lens ; i ++)
{
ll temp = a[i].data;
ll ts = 0;
while(n / temp >= 1)
{
ts += n / temp;
temp = temp * a[i].data;
}
if(ts < a[i].times)
{
flag = false;
break;
}
}
if(flag)
{
cout << m <<" divides "<< n <<"!" << endl;
}
else cout << m<< " does not divide " << n << "!"<< endl;
}
}