质数问题总结

质数(质数又称素数)是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。
1、在一个大于1的数a和它的2倍之间(即区间(a, 2a]中)必存在至少一个素数。
2、存在任意长度的素数等差数列。 [1]
3、一个偶数可以写成两个合数之和,其中每一个合数都最多只有9个质因数。(挪威数学家布朗,1920年)
4、一个偶数必定可以写成一个质数加上一个合成数,其中合数的因子个数有上界。(瑞尼,1948年)
5、一个偶数必定可以写成一个质数加上一个最多由5个因子所组成的合成数。后来,有人简称这结果为 (1 + 5)(中国潘承洞,1968年)
6、一个充分大偶数必定可以写成一个素数加上一个最多由2个质因子所组成的合成数。简称为 (1 + 2)
1.判断质数

int isPrime(int n){
	//1不是素数,所以要先判断传入的参数是否为1 
	if(n==1){
		//如果为1则返回0 
		return 0;
	}else{
		//sqrt()函数需要cmath头文件 
		for(int i=2;i<=sqrt(n);i++){
		if(n%i==0){
			return 0;
		}
	}
	//没有在2~m-1之间找到n的商,证明此数是素数,返回1 
	return 1;
	}
	
}

2.求最大质因子

int GetMax(int a)//求数字a的最大质因子
{
    if(a==1)
        return 1;
    else
    {
        for(int i=2; i*i<=a; i++)
        {
            if(a%i==0)
            {
                return GetMax(a/i)>GetMax(i)?GetMax(a/i):GetMax(i);
            }
        }
        return a;
    }
}

3.判断数字n是不是质数×质数的形式

bool check(int n)//判断数字n是不是质数×质数的形式
{
    int i;
    for(i=2; i<=sqrt(n); i++)
        if(n%i==0)
            if(factor[i]&&factor[n/i])
                return true;
    return false;
}

4.素数打表

/*bool is_prime[100010];
bool factor[100010];
int p,book[100010];*/全局
void prime(int n)//从1-n的素数表
{
    int i,j;
    memset(factor,true,sizeof(factor));
    factor[0]=factor[1]=false;
    for(i=2; i<=n; i++)
    {
        if(factor[i])
            book[p++]=i;
        for(j=0; j<p&&book[j]*i<=n; j++)
        {
            factor[book[j]*i]=false;
            if(i%book[j]==0)
                break;
        }
    }
}

5.质数的son
题目大意:a和b两个人玩游戏,a给了我们钱(大雾)所以我们要让a赢。给一个数字,两个人轮流取这个数的真因数(不能包含1和这个数本身),谁不能取了谁就赢。(a先取)

样例解释:3这个数字没有真因数,所以a没法取,a直接获胜,输出0。4这个数字的真因数只有2,所以a取2,然后轮到b取,2这个数字没有真因数,所以b没法取了,b获胜输出-1。8这个数字,a先取4,然后b取2,然后a没法取了,a获胜。(如果a获胜的开局有多个就输出数字最大的那一个),666这个数字,a先取111,然后b只能取3或者37,这两个数字都没有真因数,所以a获胜。

解题思路:其实归根到底就是看到最后的那个数字是不是质数,如果谁先取到质数谁就输了,因为下一个人一定没办法再取了,所以我们尽量要让b取到质数(谁让我们收a的黑钱了呢)。

首先我们假设b最后取的质数是k,那么这个k应该是所给数字n的最大质因子,为什么呢?
1.我们要让b取质数,2.我们要让a开局取得数字尽量大,这样一来如果b取得的是最大质因子,那么就可以保证上面两种情况.
我们再看666那个例子,到最后b只能从111中取真因数,而111这个数字的真因数只有37和3,所以b只能取质数。同理我们可以让a选的那个数字是两个质数相乘的形式,这样一来b只能从两个质数里面选,不管他选什么,他都是输定了,而37刚好是666的最大质因数,没错!这就是关键,a所选的那个数字=一个质数×所给数字n的最大质因数。那么这”一个质数“怎么求呢,题目说了要让a取的数字尽量大,所以我们也要让这”一个质数“尽量大,同时我们需要满足n%(一个质数*n的最大质因数)=0,也就是说你a取得数字得是n的真因数。另外如果数字n一开始就是质数的话直接输出0(a必赢),如果数字n是质数×质数的形式的话直接输出-1(a必输,因为我们就是用这种方法对付b的)。

#include <bits/stdc++.h>

using namespace std;
bool is_prime[100010];
bool factor[100010];
int p,book[100010];
void prime(int n)//从1-n的素数表
{
    int i,j;
    memset(factor,true,sizeof(factor));
    factor[0]=factor[1]=false;
    for(i=2; i<=n; i++)
    {
        if(factor[i])
            book[p++]=i;
        for(j=0; j<p&&book[j]*i<=n; j++)
        {
            factor[book[j]*i]=false;
            if(i%book[j]==0)
                break;
        }
    }
}

int GetMax(int a)//求数字a的最大质因子
{
    if(a==1)
        return 1;
    else
    {
        for(int i=2; i*i<=a; i++)
        {
            if(a%i==0)
            {
                return GetMax(a/i)>GetMax(i)?GetMax(a/i):GetMax(i);
            }
        }
        return a;
    }
}

bool check(int n)//判断数字n是不是质数×质数的形式
{
    int i;
    for(i=2; i<=sqrt(n); i++)
        if(n%i==0)
            if(factor[i]&&factor[n/i])
                return true;
    return false;
}

int main()
{
    int t,n,i;
    scanf("%d",&t);
    prime(100010);//处理素数表
    while(t--)
    {
        scanf("%d",&n);
        if(GetMax(n)==n)//如果一个数字的最大素数因子是他本身,那么他就是个素数
            printf("0\n");
        else if(check(n))
            printf("-1\n");
        else
        {
            for(i=n/GetMax(n); i>=2; i--)//倒着找,从大到小找,找到满足条件的直接break
                if(factor[i]&&n%(i*GetMax(n))==0)
                {
                    printf("%d\n",i*GetMax(n));
                    break;
                }
        }
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值