2018年北理研究生考试复试机试第二题

哥德巴赫猜想

任何一个大于2的偶数均可表示为两个素数之和。输入m, n(6<=m<=n<=50),则把[m, n]内的所有偶数表示成两个素数之和的形式。输出这些素数及其出线的次数,输出次序按照素数出现的次数从多到少输出;若出线次数相同,按照素数从大到小输出;若偶数有多种素数相加形式,则把所有的情况都输出,每种情况占一行。

输入:8 9    输出:5 1 3 1

输入:9 10  输出:5 2

                                 7 1 3 1

输入:14 15 输出:7 2

                                   11 1 3 1

输入:8 10   输出:5 3 3 1

                                   3 2 7 1 5 1
题目说按排序输出,但是有一点没有说明确,比如10可以分成{3:1,  7:1}和{5:2},这两个是否要排序。我按照这两个不需要排序来做的,所以没有处理这个地方。

代码一:(思路注释里写的很详细了)

#include<bits/stdc++.h>

using namespace std;

vector<int> prime;	//素数数组

void su()   //素筛,来选出2~50之间的素数
{
	int a[55];
	memset(a, 0, sizeof(a));
	for(int i=2; i<=50; i++)
	{
		if(a[i]==0)  //是素数
			prime.push_back(i);
		int j=2;
		while(i*j <= 50)
			a[i*j++] = -1; 	//非素数
	}
}

bool my_cmp(pair<int, int> a, pair<int, int> b)
{
	if(a.second != b.second)	return a.second>b.second;
	return a.first>b.first;
}

vector<map<int, int> > cal(vector<map<int, int> > v1, vector<map<int, int> > v2)
{
	vector<map<int, int> > res;
	map<int, int>::iterator iter;
	for(int i=0; i<v1.size(); i++)
	{
		for(int j=0; j<v2.size(); j++)
		{
			map<int, int> n1 = v1[i];
			map<int, int> n2 = v2[j];
			map<int, int> m1, m2;
			for(iter=n1.begin(); iter!=n1.end(); iter++)
				m1[iter->first] += iter->second;
			for(iter=n2.begin(); iter!=n2.end(); iter++)
				m1[iter->first] += iter->second;
			//对m1进行排序
			//vector<pair<int, int> > temp(m1.begin(); m1.end());
			//sort(temp.begin(), temp.end(); my_cmp);
			//排完序赋给m2
			//for(int k = 0;k < temp.size();k++)
			//	m2[temp[k].first] = temp[k].second;
			res.push_back(m1);
		}
	}
	return res;
}


int main()
{
	su();	//得到2~50以内的素数表
	int n,mm;
	cin>>n>>mm;
	//最外层map存放n~m之间的素数和该数的vector, 每个数的vector又存放素数列表
	//比如 10的vector为 [ {3:1, 7:1}, {5:2} ], 8的vector为[ {3:1, 5:1 } ]
	map<int, vector<map<int, int> > > m;
	for(int i=n; i<=mm; i++)
	{
		if(i%2 == 1)	continue;  //奇数,跳过
		vector<map<int, int> > v;	//暂存该数的素数列表,map的键和值为素数以及该素数出现的次数
		for(int j=0; prime[j]<=i/2; j++)		//遍历素数数组prime,找小于i/2的素数
		{
			//如果小于i/2的素数和 i-prime[j]的素数都有
			//例如,i=8时, 3 和  5都有
			if(find(prime.begin(), prime.end(), i-prime[j]) != prime.end() )
			{
				map<int, int> temp;   //暂存此次素数组合
				temp[prime[j]]++;
				temp[i-prime[j]]++;
				v.push_back(temp);    //存入该数的素数列表
			}
		}
		m[i] = v;
	}
	

	//进行排序输出
	if(m.size() == 1)	//n~m之间只有一个素数 ,则不必排列组合,直接排序输出
	{  
		vector<map<int, int> > res = m.begin()->second;	//得到该数的素数列表
		for(int i = res.size()-1; i >= 0; i--)
		{
			//为了排序
			vector<pair<int, int> > temp(res[i].begin(), res[i].end());
			sort(temp.begin(), temp.end(), my_cmp);
			//输出
			for(int j=0; j<temp.size(); j++)
				cout<<temp[j].first<<":"<<temp[j].second<<" ";
			cout<<endl;
		}
	}
	else	//多组需要进行排列组合
	{
		map<int, vector<map<int, int> > >::iterator it = m.begin();
		vector<map<int, int> > v1 = it->second;	//得到第一个数的素数列表
		it++;
		vector<map<int, int> > v2 = it->second;	//得到第2个数的素数列表
		it++;
		//排列组合
		vector<map<int, int> > res = cal(v1, v2);
		while(it!=m.end())
		{
			vector<map<int, int> > v3 = it->second;
			res = cal(res, v3);
			it++;
		}
		//输出
		for(int i = res.size()-1; i>=0; i--)
		{
			//对结果的每个列表进行排序
			vector<pair<int, int> > temp(res[i].begin(), res[i].end());
			sort(temp.begin(), temp.end(), my_cmp);
			for(int j = 0;j < temp.size();j++)
				cout<<temp[j].first<<":"<<temp[j].second<<" ";
			cout<<endl;
		}
	}
	return 0;
}

代码二:递归

#include<iostream>
#include<map>
using namespace std;
int prime[15]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47};
bool judge(int x)  //判断是否是素数
{
	for(int i=0;i<15;i++)
	{
		if(prime[i]==x)return true;
	}
	return false;
}
void dfs(map<int,int> Q,int n,int m)
{
	if(n>m)    //边界,输出
	{
		map<int,int>::iterator it,max;
		while(Q.empty()==false)
		{
			max=Q.begin();
			for(it=Q.begin();it!=Q.end();it++)
			{
				if(max->second<it->second||max->second==it->second&&max->first>it->first)max=it;
			}
			if(max->second>0)cout<<max->first<<":"<<max->second<<" ";
			Q.erase(max);
		}
		cout<<endl;
	}
	else
	{
		for(int i=2;i<=n/2;i++)
		{
			if(judge(i)&&judge(n-i))
			{
				Q[i]++;
				Q[n-i]++;
				dfs(Q,n+2,m);
				Q[i]--;
				Q[n-i]--;
			}
		}
	}
}
int main()
{
	int n,m;
	while(cin>>n>>m)
	{
		map<int,int>Q;
		Q.clear();
		if(n%2==0)dfs(Q,n,m);
		else dfs(Q,n+1,m);
	}
	return 0;
}

 

 

 

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值