素数相关习题

判断素数

素数定义:质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数(规定1既不是质数也不是合数)

判断一个数n是不是素数,最简单的方法就是直接遍历,看看从2到n-1是否能够整除n。如下:

bool isPrime(int n){
    if(1==n) return false;
    for(int i=2;i<n;i++){
        if(n%i==0)
            return false;
    }
    return true;
}

因为如果能找到两个因子相乘等于n的话,那么这两个数一定是位于sqrt(n)的两边的,所以我们只用判断[2,sqrt(n)]之间是否有数能够整除n即可,

bool isPrime(int n){
    if(1==n) return false;
    for(int i=2;i<=sqrt(n);i++){
        if(n%i==0)
            return false;
    }
    return true;
}

找出1~n内所有的素数

利用排除法,找到一个素数,那么该素数的倍数就应该都被排除。

#include<bits/stdc++.h>
using namespace std;

bool isPrime(int n){
    if(1==n) return false;
    for(int i=2;i<=sqrt(n);i++){
        if(n%i==0)
            return false;
    }
    return true;
}

vector<int> findPrime(int n){
    if(n<=1) return {};

    vector<int> temp(n+1);
    for(int i=2;i<=n;i++){
        //如果i是素数,那i的倍数就得排除
        if(isPrime(i)){
            for(int j=i*i;j<=n;j+=i)
                temp[j]=-1;
        }else
        {
            temp[i]=-1;
        }
    }
    vector<int> res;
    for(int i=2;i<n+1;i++){
        if(temp[i]!=-1)
            res.push_back(i);
    }
    return res;
}
int main(){


    int n;
    while(cin>>n){
        vector<int> res=findPrime(n);
        for(auto& i: res)
            cout<<i<<" ";
        cout<<endl;
    }
    
    system("pause");
    return 0;
}

在这里插入图片描述

素数相关的面试题

来自 猜数游戏

牛牛和羊羊在玩一个有趣的猜数游戏。在这个游戏中,牛牛玩家选择一个正整数,羊羊根据已给的提示猜这个数字。第i个提示是"Y"或者"N",表示牛牛选择的数是否是i的倍数。
例如,如果提示是"YYNYY",它表示这个数使1,2,4,5的倍数,但不是3的倍数。

注意到一些提示会出现错误。
例如: 提示"NYYY"是错误的,因为所有的整数都是1的倍数,所以起始元素肯定不会是"N"。此外,例如"YNNY"的提示也是错误的,因为结果不可能是4的倍数但不是2的倍数。

现在给出一个整数n,表示已给的提示的长度。请计算出长度为n的合法的提示的个数。
例如 n = 5:
合法的提示有:
YNNNN YNNNY YNYNN YNYNY YYNNN YYNNY
YYNYN YYNYY YYYNN YYYNY YYYYN YYYYY
所以输出12

输入描述:
输入包括一个整数n(1 ≤ n ≤ 10^6),表示已给提示的长度。

输出描述:
输出一个整数,表示合法的提示个数。因为答案可能会很大,所以输出对于1000000007的模

示例1
输入

5

输出

12

思路: 设dp[i]表示输入长度为i时的合法的提示个数,那么根据i的分类可能存在下面几种情况:

  • i为素数,由于素数和前面的所有数都没有依赖关系,即第i位可以为Y或者N,所以dp[i]=dp[i-1]*2;

  • i不是素数的幂次,也就是像6这样的数字,你会发现,它已经被第2位和第3位唯一确定了。例如23分别是YY,那么6一定是Y;23分别是YN或NY或NN,6一定是N,所以说这时候有dp[i]=dp[i-1]

  • i是素数的幂次,它不能唯一确定。例如4,当2为Y时,4不确定,可以是Y,也可以是N。将4和2放入集合 { 2 , 2 2 } {2,2^2} 222,所以有NN,YN,YY三种情况(3=2+1)。那么引申一下,加入8就是3个元素的集合 { 2 , 2 2 , 2 3 } {2,2^2,2^3} 222,23,共4种情况(4=3+1); 将3和9放入集合 { 3 , 3 2 } {3,3^2} 332,有NN,YN,YY三种情况(3=2+1),以此类推。最后将这些情况相乘即可,因为这些集合之间相互不影响

因此,从上面分析中可以看出,长度为n的各位可以分为两类:

  • 位数为素数或素数的幂次:这些位上的可能性取决于素数的幂次且小于n的那些数。
  • 位数不是素数且不是素数的幂次:当素数位的字符确定了,这些位上的字符也都确定,即都只有一种可能性;

所以, 合法提示组合数问题转化为求所有小于等于n的素数及他们的幂次数的组合数的乘积。也就是把每一个素数和它的幂次归为一类,求出每一类的合法提示组合数,由于类与类之间没有重叠关系,因此总的组合数为所有类的组合数的乘积

#include<bits/stdc++.h>
using namespace std;

int main(){
    int n;
    while(cin>>n){
        long long res=1;
        vector<bool> visited(n+1,false);
        for( int i=2;i<=n;i++){
            if(visited[i]) continue;
            
            //排除素数的倍数
            //这里改成for(int j=i*i;j<=n;j+=i)也是可以的
            for(int j=2*i;j<=n;j+=i){
                visited[j]=true;
            }
            //在n的范围内,该素数的幂次最多为多大
            long long temp=i;
            int count=0;
            while(temp<=n){
                temp*=i;
                count++;
            }
            //计算所有素数幂次集合的乘积
            res=res*(count+1)%1000000007;
        }
       
      cout<<res<<endl;

    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值