简单素数题

Goldbach’s Conjecture

hdu1397

问题描述

哥德巴赫猜想:对于任何大于或等于4的偶数n,存在至少一对素数p1和p2,使得n = p1 + p2。
这个猜想既没有得到证实,也没有遭到拒绝。没有人确定这个猜想是否成立。然而,对于给定的偶数,可以找到这样一对素数(如果有的话)。这里的问题是编写一个程序,报告满足给定偶数猜想条件的所有素数对的个数。
一个偶数序列作为输入。对应于每个数字,程序应该输出上面提到的对的数量。注意,我们感兴趣的是本质上不同的对的数量,因此你不应该把(p1, p2)和(p2, p1)单独当作两对。

输入

每个输入行中都有一个整数。你可以假设每个整数都是偶数,大于或等于4,小于2的15次方。输入的末尾由一个数字0表示。

输出

每个输出行应该包含一个整数。输出中不应该出现其他字符。

分析:

直接打表操作。

代码:
#include<iostream>
#include<cstdio>
typedef long long ll;
const int inf=0x3f3f3f3f;
const int inn=0x80808080;
using namespace std;
const int maxm=4e4+5;
int isprime[maxm];
int prime[maxm];
int cnt=0;
void init(){
    for(int i=2;i<maxm;i++){
        isprime[i]=1;
    }
    for(int i=2;i<maxm;i++){
        if(isprime[i]){
            prime[cnt++]=i;
            for(int j=i+i;j<maxm;j+=i){
                isprime[j]=0;
            }
        }
    }
}
int main(){
    init();
    int n;
    while(cin>>n&&n){
        int ans=0;
        for(int i=0;i<cnt;i++){
            if(prime[i]>n/2)break;
            if(isprime[n-prime[i]]){
                ans++;
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}


Goldbach’s Conjecture

poj2262

问题描述

1742年,德国业余数学家克里斯蒂安·哥德巴赫给莱昂哈德·欧拉写了一封信,他在信中作了如下推测:
任何大于4的偶数都可以
写成两个奇数素数的和。
例如:
8 = 3 + 5。3和5都是奇数素数。
20 = 3 + 17 = 7 + 13。
42 = 5 + 37 = 11 + 31 = 13 + 29 = 19 + 23。
时至今日,这个猜想是否正确仍未得到证实。(哦,等等,我当然有证据,但是把它写在这页边上太长了。)
无论如何,现在的任务是验证哥德巴赫对所有小于100万的偶数的猜想。

输入

输入将包含一个或多个测试用例。
每个测试用例由一个偶数n组成,其中6 <= n < 1000000。
输入将被n的0值终止。

输出

对于每个测试用例,打印n = a + b形式的一行,其中a和b是奇数素数。数字和操作符之间应该像下面的示例输出中那样用一个空格隔开。如果有一对以上的奇数素数加起来等于n,选择差b - a最大的一对。如果没有这样的一对,打印一行“Goldbach’s conjecture is wrong.”

分析:

这题和上一期基本一样,不多bb。

代码:
#include<iostream>
#include<cstdio>
typedef long long ll;
const int inf=0x3f3f3f3f;
const int inn=0x80808080;
using namespace std;
const int maxm=1e6+5;
int isprime[maxm];
int prime[maxm];
int cnt=0;
void init(){
    for(int i=2;i<maxm;i++){
        isprime[i]=1;
    }
    for(int i=2;i<maxm;i++){
        if(isprime[i]){
            prime[cnt++]=i;
            for(int j=i+i;j<maxm;j+=i){
                isprime[j]=0;
            }
        }
    }
}
int main(){
    init();
    int n;
    while(scanf("%d",&n)!=EOF&&n){
        int ok=1;
        for(int i=0;i<cnt;i++){
            if(prime[i]>n/2){
                ok=0;
                break;
            }else{
                if(isprime[n-prime[i]]){
                    printf("%d = %d + %d\n",n,prime[i],n-prime[i]);
                    break;
                }
            }
        }
        if(!ok){
            printf("Goldbach's conjecture is wrong.\n");
        }
    }
    return 0;
}


Summation of Four Primes

UVA10168

问题描述

欧拉在他的一个经典定理中证明质数在数上是无限的。但是每一个
数字可以表示为四个正素数的和吗?我不知道答案。可能是你
可以帮助! ! !

输入

输入每一行包含一个整数N (N≤10000000)。这是你要的号码
必须表示为四个素数的和。输入在文件末尾终止。

输出

每一行输入有一行输出,其中包含四个素数
给定的条件。如果数字不能表示为四个素数的和,则打印
线的可能。“排成一行。可以有多种解决方案。任何好的解决方案都可以
接受。

分析:

小于8的数字肯定impossible。可以直接判断。
大于8的数字分情况:
如果是奇数,可以先拆出2和3
如果是偶数,可以先拆出2和2
去掉两个数字之后就变成了哥德巴赫猜想:一个偶数能由两个质数相加组成
又和前面的题目差不多了。

代码:
#include<iostream>
#include<cstdio>
typedef long long ll;
const int inf=0x3f3f3f3f;
const int inn=0x80808080;
using namespace std;
const int maxm=1e7+5;
int isprime[maxm];
int prime[maxm];
int cnt=0;
void init(){
    for(int i=2;i<maxm;i++){
        isprime[i]=1;
    }
    for(int i=2;i<maxm;i++){
        if(isprime[i]){
            prime[cnt++]=i;
            for(int j=i+i;j<maxm;j+=i){
                isprime[j]=0;
            }
        }
    }
}
int main(){
    init();
    int n;
    while(scanf("%d",&n)!=EOF){
        if(n<8){
            printf("Impossible.\n");
            continue;
        }
        if(n%2){
            printf("2 3 ");
            n-=5;
        }else{
            printf("2 2 ");
            n-=4;
        }
        for(int i=0;i<cnt;i++){
            if(isprime[n-prime[i]]){
                printf("%d %d\n",prime[i],n-prime[i]);
                break;
            }
        }
    }
    return 0;
}


Primed Subsequence

UVA10871

问题描述

给定一个长度为n的正整数序列,我们定义一个素数子序列为一个连续子序列
长度至少为2的子序列,其和为一个大于或等于2的素数。
例如,给定序列:
3 5 6 3 8
有两个长度为2的素数子序列(5 + 6 = 11和3 + 8 = 11),其中一个素数子序列
一个长度为3(6 + 3 + 8 = 17)的素数子序列,一个长度为4(3 + 5 + 6 + 3 = 17)的素数子序列。

输入

输入由一系列测试用例组成。第一行包含一个整数t (1 < t < 21),即数字
的测试用例。每个测试用例由一行组成。这一行以整数n开始,0 < n < 10001,
由n个小于10000的非负数组成。你应该注意到
80%的测试用例在序列中最多有1000个数字。

输出

对于每个序列,打印“最短素数子序列是长度x:”,其中x是长度
用空格隔开的最短素数子序列,然后是最短素数子序列。
如果有多个这样的序列,请先打印第一个。如果没有这样的序列,
打印“This sequence is anti-primed.”。

分析:

最多1e4个数字每个数字最大1e4,理论上可以上到1e4*1e4=1e8;
判断大素数用筛选法和试除法
另外求区间和用前缀和相减比较快
枚举每一段区间,但是循环最外层必须是长度(注释里面有说)

代码:
#include<iostream>
#include<cstdio>
typedef long long ll;
const int inf=0x3f3f3f3f;
const int inn=0x80808080;
using namespace std;
const int maxm=1e4+5;
int isprime[maxm];
int prime[maxm];
int cnt=0;
void init(){
    for(int i=2;i<maxm;i++){
        isprime[i]=1;
    }
    for(int i=2;i<maxm;i++){
        if(isprime[i]){
            prime[cnt++]=i;
            for(int j=i+i;j<maxm;j+=i){
                isprime[j]=0;
            }
        }
    }
}
int judge(int x){
    if(x<maxm){
        return isprime[x];
    }else{
        for(int i=0;i<cnt;i++){
            if(x%prime[i]==0){
                return 0;
            }
        }
        return 1;
    }
}
int main(){
    init();
    int T;
    scanf("%d",&T);
    while(T--){
        int n;
        int a[maxm];
        int add[maxm];
        scanf("%d",&n);
        add[0]=0;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            add[i]=a[i];//前缀和
            if(i-1)add[i]+=add[i-1];
        }
        int ok=0;
        for(int j=2;j<=n-2;j++){//因为需要长度最小的第一个答案,所以先枚举长度再枚举起点
            for(int i=1;i+j-1<=n;i++){//枚举起点
                int sum=add[i+j-1]-add[i-1];
                if(judge(sum)){
                    printf("Shortest primed subsequence is length %d:",j);
                    for(int k=i;k<i+j;k++){
                        printf(" %d",a[k]);
                    }
                    printf("\n");
                    ok=1;
                    break;
                }
            }
            if(ok)break;
        }
        if(!ok){
            printf("This sequence is anti-primed.\n");
        }
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值