哥德巴赫猜想
任何一个大于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;
}