【c++算法刷题笔记】——洛谷

1. 洛谷练习——P1579 哥德巴赫猜想(升级版)

题目描述:
现在请你编一个程序验证哥德巴赫猜想。
先给出一个奇数n,要求输出3个质数,这3个质数之和等于输入的奇数。
输入格式:
仅有一行,包含一个正奇数n,其中9<n<20000
输出格式:
仅有一行,输出3个质数,这3个质数之和等于输入的奇数。相邻两个质数之间用一个空格隔开,最后一个质数后面没有空格。如果表示方法不唯一,请输出第一个质数最小的方案,如果第一个质数最小的方案不唯一,请输出第一个质数最小的同时,第二个质数最小的方案。
分析过程:
如果一个奇数能分为三个数和,则只有两种情况①偶数+偶数+奇数 ②奇数+奇数+奇数。如果在加上三个数必须是质数这个条件则① 2 + 2 + n 4 2 +2+n-4 (偶质数只有 2 2 ,如果 n 4 n-4 为质数则成立)②质数+质数+质数(这三个数为大于等于3的奇数)
代码:

#include<iostream>
#include<cmath>
using namespace std;
bool isPrime_3(int num);
int main()
{
	int n;
	cin >> n;
	if (isPrime_3(n - 4))//如果满足第一种情况直接输出返回
	{
		cout << 2 << " " << 2 << " " << n - 4 << endl;
		return 0;
	}
	else
		for (int i = 3; i < n; i += 2)
		{
			if (isPrime_3(i)) //i必须是质数
			{
				for (int j = i; i < n; j += 2)
					//这里先判断n-j-i是不是奇数(因为判断奇数比较快) 另一种判断奇数(n-j-i)&1
					if ((n - j - i) % 2 == 1&& isPrime_3(j) && isPrime_3(n - j - i))
					{
						cout << i << " " << j << " " << n - j - i << endl;
						return 0;
					}
			}
		}
}
bool isPrime_3(int num)//优化后的判断质数 第一次洛谷刷题学到的(详细看【c++算法刷题笔记】——洛谷<1>)
{
	if (num == 2 || num == 3)
		return 1;
	if (num % 6 != 1 && num % 6 != 5)
		return 0;
	int tmp = sqrt(num);
	for (int i = 5; i <= tmp; i += 6)
		if (num % i == 0 || num % (i + 2) == 0)
			return 0;
	return 1;
}

总结:
这是看洛谷一个牛犇的想法,为什么可以这么做?题目中很明显只让输出一组解,所以只需要在 i i j j 都是质数的前提下判断 n j i n-j-i 这个数是不是质数,如果是就输出!而且对于分析过程将题目简化值得学习

2. 关于取模运算的优化技巧——P1226 【模板】快速幂||取余运算

( A 1 + A 2 + A 3 + + A n ) m o d X = ( A 1 m o d X + A 2 m o d X + A 3 m o d X + + A n m o d X ) m o d X (A_1+A_2+A_3+\cdots+A_n)modX=(A_1modX+A_2modX+A_3modX+\cdots+A_nmodX)modX
( A 1 × A 2 × A 3 × × A n ) m o d X = ( A 1 m o d X × A 2 m o d X × A 3 m o d X × × A n m o d X ) m o d X (A_1×A_2×A_3×\cdots×A_n)modX=(A_1modX×A_2modX×A_3modX×\cdots×A_nmodX)modX

3.洛谷练习——P1032 字串变换.

题目描述:
已知有两个字串 A A B B 及一组字串变换的规则(至多 6 6 个规则):
A 1 > B 1 A_1->B_1
A 2 > B 2 A_2->B_2
规则的含义为:在 A A 中的子串 A 1 A_1 可以变换成 B 1 B_1 A 2 A_2 可以变换成 B 2 B_2
输入格式:
A A B B
A 1 A_1 B 1 B_1
A 2 A_2 B 2 B_2
. . . . . .....
所有字符串长度的上限为 20 20
输出格式:
若在 10 10 步(包含 10 10 步)以内能将 A A 变换为 B B ,则输出最少的变换步数;否则输出"NO ANSWER!"
分析过程:
这里明显是个宽搜题BFS,如果拿到手里不知道怎么运用宽搜(字符串)。这题的难点:①字符串宽搜如何更新。②优化!用到 m a p < s t r i n g , i n t > map<string,int>
代码:

#include<iostream>
#include<queue>
#include<map>
#include<string>
using namespace std;
int main()
{
	map<string, int>mp;
	string a, b;
	cin >> a >> b;
	string x[7], y[7];
	int n = 0;
	while (cin >> x[n] >> y[n])
		n++;
	queue<string>Q;
	queue<int>s;
	Q.push(a);//记录字符串
	s.push(0);//记录布数
	while (!Q.empty())
	{
		if (Q.front() == b)//如果得到结果直接返回
		{
			cout << s.front() << endl;
			return 0;
		}
		if (s.front() == 10)
		{
			cout << "NO ANSWER!" << endl;
			return 0;
		}
		string t = Q.front();
		if (mp.count(t))
		{
			Q.pop();
			s.pop();
			continue;
		}
		mp[t] = 1;//将字符串映射到mp中的一个位置
		for (int i = 0; i < n; i++)
		{
			int p = 0;
			while (t.find(x[i], p) != -1)//查找成功返回位置否则返回-1
			{
				p = t.find(x[i], p);//在t字符串中从p这个位置开始查找x[i]字符串
				Q.push(t.substr(0, p) + y[i] + t.substr(p + x[i].length()));//字符串替换,substr(0,p)将字符串中0-p的字符取出来
				s.push(s.front() + 1);
				p++;
			}
		}
		Q.pop();
		s.pop();

	}
	cout << "NO ANSWER!" << endl;
	return 0;
}

总结:
本题是我参考b站一个up主的解答。用 m a p map 这个函数作为原来的 v i s i t visit 记录已经遍历过的点优化BFS,而且学到了字符串的拼接更新。

4.洛谷练习——P1012 拼数

题目描述:
设有 n n 个正整数 ( n 20 ) (n≤20) ,将它们联接成一排,组成一个最大的多位整数。
例如: n = 3 n=3 时, 3 3 个整数 13 , 312 , 343 13,312,343 联接成的最大整数为: 34331213 34331213
又如: n = 4 n=4 时, 4 4 个整数 7 , 13 , 4 , 246 7,13,4,246 联接成的最大整数为: 7424613 7424613
输入格式:
第一行,一个正整数 n n
第二行, n n 个正整数。
输出格式:
一个正整数,表示最大的整数。
分析过程:
刚拿到这个题的时候,感觉简单啊,不就是个字符串比较,最大的放最前面如果是 0 0 不输出就ok了?其实这题远远没有那么容易如果不是测试点我可能跟不想不到哪里出了问题。比如 a = 32 b = 321 a=32,b=321 明显 32321 > 32132 32321>32132 但是如果你按字符串的比较方法得到的结果确实后者所以我们不是比较字符串 a a b b 的大小,而是比较字符串 a + b a+b b + a b+a 的大小!
代码:

#include<iostream>
#include<cstring>
using namespace std;
int main()
{
	string arr[21];
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> arr[i];
	for (int i = 1; i <= n - 1; i++)
	{
		for (int j = 1; j <= n - i; j++)
		{
			if ((arr[j]+arr[j+1])<(arr[j+1]+arr[j]))
			{
				string p = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = p;
			}
		}
	}
	if (arr[1] == "0")//注意:如果为0最终结果只需要输出一个0
		cout << 0 << endl;
	else
	{
		for (int i = 1; i <= n; i++)
			cout << arr[i];
	}
	return 0;
}

总结:
这一题我自己先用字符串比较硬凑条件怼出来了,我看了别的神犇的方法恍然大悟,柳暗花明。为什么我想不到呢?可能见得多了就知道了!所以记录下来方便复习

5.洛谷练习——P1538 迎春舞会之数字舞蹈

此代码来自b站up主——嘉持

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int n, h, w;
string a;
string c[5] = {
" -       -   -       -   -   -   -   -  ",
"| |   |   |   | | | |   |     | | | | | ",
"         -   -   -   -   -       -   -  ",
"| |   | |     |   |   | | |   | | |   | ",
" -       -   -       -   -       -   -  ",
};
char f(int x, int y)
{
	if (x >= 1)
		x = max(x - n + 1, 1);
	if (x >= 3)
		x = max(x - n + 1, 3);
	int m = y / (n + 3);
	y %= (n+3);
	if (y > 0)
		y = max(y - n + 1, 1);
	return c[x][y + (a[m] - '0')* 4];
}
int main()
{
	cin >> n>> a;
	h = 2 * n + 3;
	w = (n + 3) * (a.length());
	for (int i = 0; i < h; i++)
	{
		for (int j = 0; j < w; j++)
			cout << f(i, j);
		cout << endl;
	}
	return 0;
}

总结:
这题把我心态搞崩了,啥也不想写,看上方老师的视频讲解吧。

2020/3/1第二次刷洛谷,前几天学习数据结构算法的知识比如dfs,bfs,然后又刷了几十道题不过现在有刷不懂了又开始看算法hhh

猜你喜欢

转载自blog.csdn.net/Fighting_Peter/article/details/104442105
今日推荐