题目描述:
Time Limit: 1000 ms
Memory Limit: 256 mb
给定n,a求最大的k,使n!可以被a^k整除但不能被 a^(k+1)整除。
输入输出格式:
输入格式:
两个整数n(2<=n<=1000),a(2<=a<=1000)
输出格式:
一个整数.
输入输出样例:
输入样例:
6 10
输出样例:
1
思路分析:
既然要求整除,说明每个素因子都是可以抵消的,这样我们就可以求解了(注意这里n!的素因数可以比a^k 多,但是必须包含a^k的所有素因数)
整体流程:
- 求n!的素因数,并存储在数组factor_中,以素因数作为下标,对应的值++(这样可以方便统计每个素因数的个数)
- 求a的素因数,并存储在数组factor中,以素因数作为下标,对应的值++
- 求两个数组素因数对应下标的值的商并取最小值(这个就是k)
代码如下:
#include<bits/stdc++.h>
using namespace std;
int n,a,k;
//线性筛质因数
const int maxn=1010;
int prime[maxn];
void getPrime(){
memset(prime,0,sizeof(prime));
for(int i=2;i<=maxn;i++){
if(!prime[i])
prime[++prime[0]]=i;
for(int j=1;j<=prime[0]&&prime[j]*i<=maxn;j++)
{
prime[prime[j]*i]=1;
if(i%prime[j]==0)
break;
}
}
}
int factor[1000];
int factor_[1000];
int main(){
getPrime();
cin>>n>>a;
for(int i=1;i<=prime[0];i++){
if(a<prime[i])
break;
while(a%prime[i]==0)
{
factor[prime[i]]++;
a/=prime[i];
}
}
for(int i=2;i<=n;i++)
{
int tmp=i;
for(int j=1;j<=prime[0];j++){
if(tmp<prime[j])
break;
while(tmp%prime[j]==0)
{
factor_[prime[j]]++;
tmp/=prime[j];
}
}
}
int ans=1000;
for(int i=2;i<=maxn;i++)
if(factor[i]!=0 && factor[i]<=factor_[i])
ans=min(ans,factor_[i]/factor[i]);
cout<<ans;
}
总结:
其实这道题目最重要的知识点就是分解素因数,而分解素因数的本质知识点还是素数筛,这里的线性素数筛方法是一种高效的筛选方法,足够应付和素数相关的任何问题。下面详细理解一下素数筛的原理:
const int maxn=1000000+5;
int prime[maxn];//用于存储素数,prime[0]是素数的个数
void getPrime(){
memset(prime,0,sizeof(prime));
for(int i=2;i<=maxn;i++){
if(!prime[i])//如果是素数的话存入数组(注意这里素数是全部存在了prime数组的前prime[0]位)
prime[++prime[0]]=i;
for(int j=1;j<=prime[0]&&prime[j]*i<=maxn;j++)//用所得的素数筛掉素数的倍数
{
prime[prime[j]*i]=1;
if(i%prime[j]==0)//如果被小于i的数整除,就说明i不是素数
break;
}
}
}