Goldbach’s Conjecture
问题描述
哥德巴赫猜想:对于任何大于或等于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
问题描述
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
问题描述
欧拉在他的一个经典定理中证明质数在数上是无限的。但是每一个
数字可以表示为四个正素数的和吗?我不知道答案。可能是你
可以帮助! ! !
输入
输入每一行包含一个整数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
问题描述
给定一个长度为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;
}