整除问题(上交机试)

题目描述:
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的所有素因数)
整体流程:

  1. 求n!的素因数,并存储在数组factor_中,以素因数作为下标,对应的值++(这样可以方便统计每个素因数的个数)
  2. 求a的素因数,并存储在数组factor中,以素因数作为下标,对应的值++
  3. 求两个数组素因数对应下标的值的商并取最小值(这个就是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;
        }
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值