数论专题题记1



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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值