A - Goldbach’s Conjecture(筛选素数模板,验证哥德巴赫思想)
?题目链接:http://poj.org/problem?id=2262 ?
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
const int Max_n=1000005;
typedef long long LL;
int prime[Max_n],is_prime[Max_n];
int num;
void get_prime(){
for(int i=2;i<=Max_n;i++) is_prime[i]=true;
for(int i=2;i<=sqrt(Max_n);i++){
if(is_prime[i]){
for(int j=i*i;j<=Max_n;j+=i)
is_prime[j]=false;
}
}
num=1;
for(int i=2;i<=Max_n;i++)
if(is_prime[i])
prime[num++]=i;
}
int main(){
get_prime();
int n;
while(~scanf("%d",&n)&&n){
for(int i=1;i<num;i++){
if(binary_search(prime+1,prime+num,n-prime[i])){
printf("%d = %d + %d\n",n,prime[i],n-prime[i]);
break;
}
}
}
return 0;
}
B - Prime Gap(素数,二分)
?题目链接:http://poj.org/problem?id=3518 ?
?还得借助翻译才能搞,还搞了一个二分去查找去做(重点是没往枚举上面去想,百度题解看到的),时间给的比较大,枚举就可以过去.
//枚举
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
const int Max_n=1299709;//过大MLE
typedef long long LL;
int prime[Max_n],is_prime[Max_n];
int num;
void get_prime(){
for(int i=2;i<=Max_n;i++) is_prime[i]=true;
for(int i=2;i<=sqrt(Max_n);i++){
if(is_prime[i]){
for(int j=i*i;j<=Max_n;j+=i)
is_prime[j]=false;
}
}
num=1;
for(int i=2;i<=Max_n;i++)
if(is_prime[i])
prime[num++]=i;
}
int main(){
get_prime();
int n;
while(~scanf("%d",&n)&&n){
for(int i=1;i<num;i++){
if(n==prime[i]){
printf("%d\n",0);
break;
}
if(n<prime[i+1]&&n>prime[i]){
printf("%d\n",prime[i+1]-prime[i]);
break;
}
}
}
return 0;
}
//二分
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
const int Max_n=1299709;
typedef long long LL;
int prime[Max_n],is_prime[Max_n];
int num;
void get_prime(){
for(int i=2;i<=Max_n;i++) is_prime[i]=true;
for(int i=2;i<=sqrt(Max_n);i++){
if(is_prime[i]){
for(int j=i*i;j<=Max_n;j+=i)
is_prime[j]=false;
}
}
num=1;
for(int i=2;i<=Max_n;i++)
if(is_prime[i])
prime[num++]=i;
}
int binary(int n){
int l=1,r=num-1;
while(l<=r){
int mid=l+(r-l)/2;
if(prime[mid]==n) return 0;
else if(prime[mid]<n) l=mid+1;
else r=mid-1;
}
return l;
}
int main(){
get_prime();
int n;
while(~scanf("%d",&n)&&n){
int index=binary(n);
if(index) printf("%d\n",prime[index]-prime[index-1]);
else printf("0\n");
}
return 0;
}
E - Happy 2006 (欧几里得,找规律)
?题目链接:http://poj.org/problem?id=2773 ?
?本来这道题是解过的,但是今天忽然有一个奇特的想法:///素数都是奇数(除了2),与偶数互素的都是奇数,先去实现了这个想法,主要是奇数的不好实现,本来想着筛出来所有素数,然后二分算出来,比第k个与奇数互素的偶数,然后找到比这个偶数小的最小素数,然后找到有多少个素数,我们就能找到这样K个数.最后找一找第K个数是素数还是偶数. 后来没能实现 . 还是老老实实找规律.
先来说一个算是欧几里得推导出来的东西:如果x,m互素,那么就有,m×t+x与m也一定互素.(下面有具体例子.)其实我们也有gcd(x,m)=gcd(m×t+x,m);
现在我们来列举一下10,10以内的与10互素的数有1 3 5 7 9 也就是num=5;
现在依次列举出来第5个往后的数
1+10×1=11
3+10×1=13
5+10×1=15
7+10×1=17
9+10×1=19
1+10×2=21
3+10×2=23
5+10×2=25
7+10×2=27
9+10×2=29
很显然,9 1 3 5 7 9(数组下标对应0 1 2 3 4 5)是我们保存在数组里面的数字,10所乘的数就是:(k-1)/num,加上的数就是:a[k%num];
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
const int Max_n=1000005;
typedef long long LL;
int p[Max_n];
int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
int main(){
int m,k;
while(~scanf("%d%d",&m,&k)){
memset(p,0,sizeof(p));
int num=0;//与m互素且<=m的数的个数
for(int i=1;i<=m;i++)
if(gcd(m,i)==1)
p[num++]=i;
if(k%num!=0) printf("%d\n",(k/num)*m+p[k%num-1]);
else printf("%d\n",(k/num-1)*m+p[num-1]);
}
return 0;
}
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
const int Max_n=1000005;
typedef long long LL;
int p[Max_n];
int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
int main(){
int m,k;
while(~scanf("%d%d",&m,&k)){
memset(p,0,sizeof(p));
int num=0;//与m互素且<=m的数的个数
for(int i=1;i<=m;i++)
if(gcd(m,i)==1)
p[++num]=i;
p[0]=p[num];
printf("%d\n",(k-1)/num*m+p[k%num]);
}
return 0;
}