2018北理复试机试题

1. 最长回文串

输入一个字符串,输出其最长回文串的长度,以及最长回文串的个数,不区分大小写。例如
输入:aB 输出: 1 2
输入:aBA 输出: 3 1
输入:aaaa 输出: 4 1

写了一个字符串逆序的方法,遍历所有子串

#include<iostream>
#include<string>
#include<vector>
using namespace std;

string reverse(string t)
{
	char c;
	string :: iterator b = t.begin(), e = t.end()-1;
	while(b < e){
		c = *b;  *b = *e;  *e = c;
		b++;
		e--;
	}
	return t;
}

int main()
{
	string s, tmp;
	string::iterator it1, it2;
	int max_leng, num;
	while(cin >> s)
	{
		for(int i = 0; i < s.length(); i++)
			s[i] = tolower(s[i]);
			
		max_leng = num = 0;
		for(it1 = s.begin(); it1 != s.end(); it1++){
			for(it2 = it1;it2!=s.end();it2++){
				tmp = string(it1,it2+1);  //构造一个子串 
				if(tmp == reverse(tmp)){
					if(tmp.length() > max_leng){
						max_leng = tmp.length();
						num = 1;
					}
					else if(tmp.length() == max_leng)
						num++;
				}
			}
		}
		cout << max_leng << ' ' << num << endl;
	} 
} 

2.

任何一个大于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

本题难度主要在于在不同偶数之间、不同分解的组合上
从最简单的数据结构上来看,至少需要一个三维数组:v[50][50][50]

第一维代表[m,n]范围内的第几个偶数,第二维代表该偶数的第几种分解方式,第三维代表该分解方式下的一个质数,值代表的是该质数出现的次数。
例如:对于m=8,n=10

  • v[0][0][5] = 1、v[0][0][3] = 1
  • v[1][0][5] = 2、v[1][1][7] = 1、v[1][1][3] = 1
  • 其余值均为0

看起来很浪费空间,而且这么写会使后面的排序输出非常麻烦,于是将最后一维替换为map<int,int>类型。不过map<int,int>仅仅是为了保证插入的唯一性和便捷性而采用的中间结构,由于map不允许排序,故需要在排序前先转化为vector<int,int> pair<int,int>类型。
数据结构为vector<vector<map<int,int> > > v;
再让第二维的不同元素之间的不同分解方法做笛卡尔积,保存在vector<map<int, int> > res之中。
最后排序并输出即可

#include<iostream>
#include<vector>
#include<map>
#include<math.h>
#include<algorithm>
using namespace std;

vector<vector<map<int, int> > > v;
vector<map<int, int> > res;  //笛卡尔积的result
typedef vector<map<int, int> > D;

void insert(map<int, int> m1, map<int, int>& res)
{
	for (auto it = m1.begin(); it != m1.end(); it++) {
		int l = it->second;
		while (l > 0) {  //l为几就加几次    <===>   res[it->first] += it->second
			res[it->first]++;
			l--;
		}
	}
}

bool cmp(pair<int, int> p1, pair<int, int> p2)
{
	if (p1.second != p2.second)
		return p1.second > p2.second;
	return p1.first > p2.first;
}

D dikaer(D d1, D d2)
{
	if (d1.size() == 0) //第一次不用乘,直接返回d2
		return d2;

	vector<map<int, int> > res;
	for (int i = 0; i < d1.size(); i++) {
		for (int j = 0; j < d2.size(); j++) {
			map<int, int> tmp;
			insert(d1[i], tmp);  //tmp是个引用,将d1[i]的所有pair插入tmp中
			insert(d2[j], tmp);

			res.push_back(tmp);
		}
	}
	return res;
}

bool zhishu(int n)  //n为质数则返回true
{
	if (n <= 1)
		return false;
	for (int i = 2; i <= sqrt(n); i++) {
		if (n % i == 0)
			return false;
	}
	return true;
}

int main()
{
	int m, n;
	while (cin >> m, cin >> n) {
		v.clear();  
		res.clear();
		map<int, int> tmp;
		int a = 0;
		for (int i = m; i <= n; i++) {
			int b = 0;
			if (i % 2 != 0)
				continue;   //用i遍历m~n的所有偶数 	
			for (int j = 2; j < i / 2 + 1; j++) {  //用j遍历i的所有质数
				vector<map<int, int> > tv;
				v.push_back(tv);   //装个空容器防止越界
				if (zhishu(j) && zhishu(i - j)) {
					map<int, int> tm;
					v[a].push_back(tm);  //同理
					v[a][b][j]++;
					v[a][b][i - j]++;
					b++;  //分解方式++
				}
			}
			a++;  //偶数数量++
		}

		for (int i = 0; i < a; i++) //做笛卡尔乘积
			res = dikaer(res, v[i]);

		for (auto it = res.begin(); it != res.end(); it++) {  //排序并输出
			vector<pair<int, int> > r(it->begin(), it->end());   //注意是pair,不能用vector  :(
			sort(r.begin(), r.end(), cmp);
			for (auto ite = r.begin(); ite != r.end(); ite++) {
				cout << ite->first << ' ' << ite->second << "   ";
			}
			cout << endl;
		}
	}
}

这道题我在VS强大的debug下还写了好久才写对,要是在考场上怕是凉凉了

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值