【AcWing 2022 暑假每日一题】

性感素数【2022.07.08】

点击查看题目

题目链接:

跳转题目

题目描述:

“性感素数 ”是指形如 (p,p+6) 这样的一对素数。

之所以叫这个名字,是因为拉丁语管“六”叫“sex”(即英语的“性感”)。

现给定一个整数,请你判断其是否为一个性感素数。

输入格式

输入在一行中给出一个正整数 N。

输出格式

若 N 是一个性感素数,则在一行中输出 Yes,并在第二行输出与 N 配对的另一个性感素数(若这样的数不唯一,输出较小的那个)。

若 N 不是性感素数,则在一行中输出 No,然后在第二行输出大于 N 的最小性感素数。

数据范围

1 ≤ N ≤ 10^8

输入样例1:

47

输出样例1:

Yes
41

输入样例2:

21

输出样例2:

No
23

难度:简单

时/空限制:0.4s / 64MB

来源:PAT甲级真题1156

算法标签:枚举、质数、试除法

思路

先判断n本身是否符合性感素数,如果符合就输出"Yes"以及另一个素数
如果不符合性感素数,i就从n+1开始遍历搜索,比n大的数,有哪个符合性感素数,符合就输出。

代码

点击查看代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

bool judge(int x)
{
	if(x <= 1) return false;
	
	int len = sqrt(x);
	
	for(int i = 2;i <= len;i ++)
	{
		if(x % i == 0)
			return false;
	}
	
	return true;
}

int main()
{
	int n;
	cin >> n;
	
	if( judge(n) && judge(n-6) )
		cout << "Yes" << endl << n-6 << endl;
	else if(judge(n) && judge(n+6))
		cout << "Yes" << endl << n+6 << endl;
	else
	{
		cout << "No" << endl;
		for(int i = n+1;;i ++)
		{
			if( judge(i) && ( judge(i-6) || judge(i+6) ) )
			{
				cout << i << endl;
				return 0;
			}
		}
	}
	return 0;
}

校庆【2022.07.08】

点击查看题目

题目链接

跳转题目

题目描述

2019 年浙江大学将要庆祝成立 122 周年。

为了准备校庆,校友会收集了所有校友的身份证号。

现在需要请你编写程序,根据来参加校庆的所有人士的身份证号,统计来了多少校友。

输入格式

输入在第一行给出正整数 N。

随后 N 行,每行给出一位校友的身份证号(18 位由数字和大写字母 X 组成的字符串)。题目保证身份证号不重复。

随后给出前来参加校庆的所有人士的信息:

首先是一个正整数 M。

随后 M 行,每行给出一位人士的身份证号。题目保证身份证号不重复。

输出格式

首先在第一行输出参加校庆的校友的人数。

然后在第二行输出最年长的校友的身份证号 —— 注意身份证第 7−14 位给出的是 yyyymmdd 格式的生日。

如果没有校友来,则在第二行输出最年长的来宾的身份证号。题目保证这样的校友或来宾必是唯一的。

数据范围

1 ≤ N,M ≤10^5

输入样例

5
372928196906118710
610481197806202213
440684198612150417
13072819571002001X
150702193604190912
6
530125197901260019
150702193604190912
220221196701020034
610481197806202213
440684198612150417
370205198709275042

输出样例

3
150702193604190912

难度:简单

时/空限制:

0.8s / 64MB

来源:PAT甲级真题1157

算法标签

哈希表

代码思路

利用map暴力解决

相关知识

c_str()

以 char* 形式传回 string 内含字符串,如果一个函数要求char*参数,可以使用c_str()方法

s.substr(pos, len)

包含s中从pos开始的len个字符的拷贝(pos的默认值是0,len的默认值是s.size() - pos,即不加参数会默认拷贝整个s)

代码

点击查看代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <map>

using namespace std;

map <string,bool> mp;

bool cmp(string a,string b)
{
	if(a.substr(6,4) != b.substr(6,4))//比较年份
		return a.substr(6,4) < b.substr(6,4);
	if(a.substr(10,2) != b.substr(10,2))//比较月份
		return a.substr(10,2) < b.substr(10,2);
	
	return a.substr(12,2) < b.substr(12,2);
}

int main()
{
	int n , m;
	cin >> n;
	
	string s,temp;
	for(int i = 0;i < n;i ++)
	{
		cin >> s;
		mp[s] = true;
	}
	
	cin >> m;
	
	bool flag = false;
	int cnt = 0;
	
	for(int i = 0;i < m;i ++)
	{
		cin >> s;
		if(mp[s] == true)//表示该s是校友
		{
			if(flag == false)//第一个校友 
			{
				flag = true;
				temp = s;
			}
			else
			{
				if(cmp(temp,s) == false)
					temp = s;
			}
			cnt ++;
		}
		else
		{
			if(i == 0)//第一个外界人士
				temp = s;
			else
			{
				if(flag == false && cmp(temp,s) == false)
					temp = s;	
			} 
		} 
	}
	
	if(flag == true)
		cout << cnt << endl << temp.c_str() << endl;
	else
		cout << "0" << endl << temp.c_str() << endl;
	
	return 0;
}

链表合并【2022.07.08】

点击查看题目

原题链接

跳转题目

题目描述

给定两个单链表 L1=a1→a2→…→an−1→an 和 L2=b1→b2→…→bm−1→bm。

如果 n≥2m,你的任务是将较短的那个链表逆序,然后将之并入较长的链表,得到形如 a1→a2→bm→a3→a4→bm−1… 的结果。

例如给定两个链表分别为 6→7 和 1→2→3→4→5,你应该输出 1→2→7→3→4→6→5。

补充

本题中可能包含不在两个单链表中的节点,这些节点无需考虑。

输入格式

输入首先在第一行中给出两个链表 L1 和 L2 的头结点的地址,以及正整数 N,即给定的结点总数。

一个结点的地址是一个 5 位数的非负整数(可能包含前导 0),空地址 NULL 用 −1 表示。

随后 N 行,每行按以下格式给出一个结点的信息:

Address Data Next

其中 Address 是结点的地址,Data 是不超过 105 的正整数,Next 是下一个结点的地址。

题目保证没有空链表,并且较长的链表至少是较短链表的两倍长。

输出格式

按顺序输出结果链表,每个结点占一行,格式与输入相同。

数据范围

1≤N≤10^5

输入样例:

00100 01000 7
02233 2 34891
00100 6 00001
34891 3 10086
01000 1 02233
00033 5 -1
10086 4 00033
00001 7 -1

输出样例:

01000 1 02233
02233 2 00001
00001 7 34891
34891 3 10086
10086 4 00100
00100 6 00033
00033 5 -1

难度:简单

时/空限制:

0.4s / 64MB

来源:PAT甲级真题1161

算法标签:

链表、模拟

算法思路

在非面试的题目中,将链表当成数组来做。
本题中,定义两个数组,三个队列,两个数组分别存储i的值,和下一个i的地址。
使用两个for循环,将数组中的值分别转换为两个队列中。
再使用一个for循环,按照题目意思,存储到队列中。
输出第三个队列。

代码

点击查看代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>

using namespace std;

const int N = 1e5+10;

typedef pair<int , int> PII;

int v[N] , ne[N];

int main()
{
	int h1 , h2 , n;
	cin >> h1 >> h2 >> n;
	
	while(n --)
	{
		int address , data , next;
		
		cin >> address >> data >> next;
		
		v[address] = data;
		ne[address] = next;
	}
	
	vector <PII> a,b;
	for(int i = h1;i != -1;i = ne[i])
		a.push_back({i,v[i]});
	
	for(int i = h2;i != -1;i = ne[i])
		b.push_back({i,v[i]});
		
	if(a.size() < b.size()) swap(a,b);
	
	vector <PII> c;
	for(int i = 0, j = b.size() - 1;i < a.size();i += 2,j --)
	{
		c.push_back(a[i]);
		
		if(i+1 < a.size()) c.push_back(a[i+1]);
		
		if(j >= 0)	c.push_back(b[j]);
	}
	
	for(int i = 0;i < c.size();i ++)
	{
		printf("%05d %d ",c[i].first,c[i].second);
		
		if(i+1 < c.size()) printf("%05d\n",c[i+1].first);
		
		else cout << "-1" << endl;
	}
	
	return 0;
}

后缀表达式【2022.07.09】

点击查看题目

题目链接

跳转题目

题目描述

给定一个二叉表达式树,请你输出相应的后缀表达式,要求使用括号反映运算符的优先级。

输入格式

第一行包含整数 N,表示节点数量。节点编号 1∼N。

接下来 N 行,每行给出一个节点的信息(第 i 行对应第 i 个节点),格式为:

data left_child right_child

其中,data 是一个不超过 10 个字符的字符串,left_child right_child 分别是该节点的左右子节点的编号。

没有子节点(即 NULL),则用 −1 表示。

下面两图分别对应给出的两个样例。
image

输出格式

在一行中输出答案,表达式符号之间不得有空格。

数据范围

1 ≤ N ≤ 20

输入样例1:

8
* 8 7
a -1 -1
* 4 1
+ 2 5
b -1 -1
d -1 -1
- -1 6
c -1 -1

输出样例1:

(((a)(b)+)((c)(-(d))*)*)

输入样例2:

8
2.35 -1 -1
* 6 1
- -1 4
% 7 8
+ 2 3
a -1 -1
str -1 -1
871 -1 -1

输出样例2:

(((a)(2.35)*)(-((str)(871)%))+)

难度:简单

时/空限制:0.4s / 64MB

来源:PAT甲级真题1162

算法标签

递归、树的遍历

代码思路

先找出根节点,然后再根节点出进行深度优先遍历(DFS)

代码

点击查看代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

string v[25];
int l[25] , r[25];
bool st[25];

void dfs(int u)
{
	cout << "(" ;
	
	if(l[u] != -1 && r[u] != -1)//有左孩子和右孩子 
	{
		dfs(l[u]);
		dfs(r[u]);
		cout << v[u];
	}
	else if(l[u] == -1 && r[u] == -1)//没有左孩子和右孩子 
	{
		cout << v[u];
	}
	else if(l[u] == -1 && r[u] != -1)
	{
		cout << v[u];
		dfs(r[u]);
	}
	
	cout << ")";
}

int main()
{
	int n;
	cin >> n;
	
	for(int i = 1;i <= n;i ++)
	{
		cin >> v[i] >> l[i] >> r[i];
		st[l[i]] = true;
		st[r[i]] = true;
	}
	
	int root;
	for(int i = 1;i <= n;i ++)
	{
		if(!st[i])
			root = i;
	}
	
	dfs(root);
	
	return 0;
}

Dijkstra序列【2022.07.09】

点击查看题目

题目链接

跳转题目

题目描述

Dijkstra 算法是非常著名的贪心算法之一。

它用于解决单源最短路径问题,即指定一个特定源顶点,求该顶点到给定图的所有其他顶点的最短路径。

它由计算机科学家 Edsger W. Dijkstra 于 1956 年构思并在三年后出版。

在该算法中,我们需要不断维护一个包含最短路径树中顶点的集合。

在每一步中,我们找到一个尚未在集合内且与源顶点距离最小的顶点,并将其收于集合中。

因此,通过 Dijkstra 算法,我们可以逐步生成一个有序的顶点序列,我们称之为 Dijkstra 序列。

对于一个给定的图,可能有多个 Dijkstra 序列。

例如,{5,1,3,4,2} 和 {5,3,1,2,4} 都是给定图的 Dijkstra 序列。

注意,序列中的第一个顶点即为指定的特定源顶点。

你的任务是检查给定的序列是否是 Dijkstra 序列。

输入格式

第一行包含两个整数 N 和 M,表示图中点和边的数量。

点的编号 1∼N。

接下来 M 行,每行包含三个整数 a,b,c,表示点 a 和点 b 之间存在一条无向边,长度为 c。

再一行包含整数 K,表示需要判断的序列个数。

接下来 K 行,每行包含一个 1∼N 的排列,表示一个给定序列。

输出格式

共 K 行,第 i 行输出第 K 个序列的判断,如果序列是 Dijkstra 序列则输出 Yes,否则输出 No。

数据范围

1 ≤ N ≤1000
1≤M≤105,
1≤a,b≤N,
1≤c≤100,
1≤K≤100,

保证给定无向图是连通图,
保证无重边和自环(官网没提,但是经实测,官网数据符合此条件)。

输入样例:

5 7
1 2 2
1 5 1
2 3 1
2 4 1
2 5 2
3 5 1
3 4 1
4
5 1 3 4 2
5 3 1 2 4
2 3 4 5 1
3 2 1 5 4

输出样例:

Yes
Yes
Yes
No

难度:简单

时/空限制:2s / 64MB

来源:PAT甲级真题1163

算法标签:

Dijkstr、最短路

代码思路

利用Dijkstra算法的特性,Dijkstra()的序列的值是按照递增的顺序,如果发现有比这个边更小的距离,就是No,否则是Yes.

代码

点击查看代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

const int N = 1010;
const int INF = 0x3f3f3f3f;

int n , m;
int g[N][N] , dis[N];
bool st[N];
int q[N];

bool Dijkstra()
{
	memset(dis,0x3f,sizeof(dis));
	memset(st,0,sizeof(st));
	
	dis[q[0]] = 0;//第一个结点的距离为0
	
	for(int i = 0;i < n;i ++)
	{
		int t = q[i];
		
		for(int j = 1;j <= n;j ++)
			if(!st[j] && dis[j] < dis[t])
				return false;		
		
		
		st[t] = true;
		
		for(int j = 1;j <= n;j ++)
		{
			dis[j] = min(dis[j] , dis[t]+g[t][j]);
		}
	}
	
	return true;
}

int main()
{
	cin >> n >> m;
	
	memset(g,0x3f,sizeof(g));
	
	while(m --)
	{
		int a , b , c;
		cin >> a >> b >> c;
		g[a][b] = g[b][a] = c;
	}
	
	int t;
	cin >> t;
	
	while(t--)
	{
		for(int i = 0;i < n;i ++)
			cin >> q[i];
		
		if(Dijkstra()) puts("Yes");
		else puts("No");	
	}
	
	
	return 0;
}

擅长C【2022.07.09】

点击查看题目

题目链接

跳转题目

题目描述

当你被面试官要求用 C 写一个 Hello World 时,有本事像下图显示的那样写一个出来吗?image

输入格式

输入首先给出 26 个英文大写字母 A−Z,每个字母用一个 7×5 的、由 C 和 . 组成的矩阵构成。

最后在一行中给出一个句子,以回车结束。句子是由若干个单词(每个包含不超过 10 个连续的大写英文字母)组成的,单词间以任何非大写英文字母分隔。

题目保证至少给出一个单词。

输出格式

对每个单词,将其每个字母用矩阵形式在一行中输出,字母间有一列空格分隔。单词的首尾不得有多余空格。

相邻的两个单词间必须有一空行分隔。输出的首尾不得有多余空行。

数据范围

最后一行句子的总长度范围 [1,5000],
给出的单词数量范围 [1,300]。

输入样例:

..C..
.C.C.
C...C
CCCCC
C...C
C...C
C...C
CCCC.
C...C
C...C
CCCC.
C...C
C...C
CCCC.
.CCC.
C...C
C....
C....
C....
C...C
.CCC.
CCCC.
C...C
C...C
C...C
C...C
C...C
CCCC.
CCCCC
C....
C....
CCCC.
C....
C....
CCCCC
CCCCC
C....
C....
CCCC.
C....
C....
C....
CCCC.
C...C
C....
C.CCC
C...C
C...C
CCCC.
C...C
C...C
C...C
CCCCC
C...C
C...C
C...C
CCCCC
..C..
..C..
..C..
..C..
..C..
CCCCC
CCCCC
....C
....C
....C
....C
C...C
.CCC.
C...C
C..C.
C.C..
CC...
C.C..
C..C.
C...C
C....
C....
C....
C....
C....
C....
CCCCC
C...C
C...C
CC.CC
C.C.C
C...C
C...C
C...C
C...C
C...C
CC..C
C.C.C
C..CC
C...C
C...C
.CCC.
C...C
C...C
C...C
C...C
C...C
.CCC.
CCCC.
C...C
C...C
CCCC.
C....
C....
C....
.CCC.
C...C
C...C
C...C
C.C.C
C..CC
.CCC.
CCCC.
C...C
CCCC.
CC...
C.C..
C..C.
C...C
.CCC.
C...C
C....
.CCC.
....C
C...C
.CCC.
CCCCC
..C..
..C..
..C..
..C..
..C..
..C..
C...C
C...C
C...C
C...C
C...C
C...C
.CCC.
C...C
C...C
C...C
C...C
C...C
.C.C.
..C..
C...C
C...C
C...C
C.C.C
CC.CC
C...C
C...C
C...C
C...C
.C.C.
..C..
.C.C.
C...C
C...C
C...C
C...C
.C.C.
..C..
..C..
..C..
..C..
CCCCC
....C
...C.
..C..
.C...
C....
CCCCC
HELLO~WORLD!

输出样例:

C...C CCCCC C.... C.... .CCC.
C...C C.... C.... C.... C...C
C...C C.... C.... C.... C...C
CCCCC CCCC. C.... C.... C...C
C...C C.... C.... C.... C...C
C...C C.... C.... C.... C...C
C...C CCCCC CCCCC CCCCC .CCC.

C...C .CCC. CCCC. C.... CCCC.
C...C C...C C...C C.... C...C
C...C C...C CCCC. C.... C...C
C.C.C C...C CC... C.... C...C
CC.CC C...C C.C.. C.... C...C
C...C C...C C..C. C.... C...C
C...C .CCC. C...C CCCCC CCCC.

难度:简单

时/空限制:0.4s / 64MB

来源:PAT甲级真题1164

算法标签

模拟、字符串处理

代码思路

利用三维数组,存储每个单词的字符表示,再根据输出结果,创建一个7*60的矩阵,将需要输出的字符,填入矩阵中,最后输出矩阵。

代码

点击查看代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

char g[26][7][6];//存储每个字母的字符 

bool flag = true;//用来判断是不是第一个单词 

void output(string s)
{
    if(s.empty()) return;//判断s是否为空 

    if(flag) flag = false;
    else cout << endl;


    char ans[7][60]={0};

    for(int i = 0;i < s.size();i ++)
        for(int j = 0;j < 7;j ++)
            for(int k = 0;k < 5;k ++)
                ans[j][i*6+k] = g[s[i]-'A'][j][k];

    for(int i = 1;i < s.size();i ++)
        for(int j = 0;j < 7;j ++)
            ans[j][i*6-1] = ' ';


    for(int i = 0;i < 7;i ++)
        cout << ans[i] << endl;
}

int main()
{
    for(int i = 0;i < 26;i ++)
        for(int j = 0;j < 7;j ++)
            cin >> g[i][j];

    string word;
    char c;

    while((c = getchar()) != -1)
    {
        if(c >= 'A' && c <= 'Z') word += c;
        else
        {
            output(word);
            word = "";
        }
    }

    output(word);

    return 0;
}

区块反转【2022.07.12】

点击查看题目

题目链接

链接

题目描述

给定一个单链表 L,我们将每 K 个结点看成一个区块(链表最后若不足 K 个结点,也看成一个区块),请编写程序将 L 中所有区块的链接反转。

例如:给定 L 为 1→2→3→4→5→6→7→8,K 为 3,则输出应该为 7→8→4→5→6→1→2→3

补充

本题中可能包含不在单链表中的节点,这些节点无需考虑。

输入格式

第 1 行给出第 1 个结点的地址、结点总个数正整数 N、以及正整数 K,即区块的大小。结点的地址是 5 位非负整数(可能包含前导 0),NULL 地址用 −1 表示。

接下来有 N 行,每行格式为:

Address Data Next
其中 Address 是结点地址,Data 是该结点保存的整数数据,Next 是下一结点的地址。

输出格式

对每个测试用例,顺序输出反转后的链表,其上每个结点占一行,格式与输入相同。

数据范围

1 ≤ K ≤ N ≤ 10^5

输入样例:

00100 8 3
71120 7 88666
00000 4 99999
00100 1 12309
68237 6 71120
33218 3 00000
99999 5 68237
88666 8 -1
12309 2 33218

输出样例:

71120 7 88666
88666 8 00000
00000 4 99999
99999 5 68237
68237 6 00100
00100 1 12309
12309 2 33218
33218 3 -1

难度:简单

时/空限制:0.4s / 64MB

来源:PAT甲级真题1165

算法标签

模拟链表

代码

点击查看代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

const int N = 100010;
int d[N] , ne[N];
int n , k , h;

int main()
{
    cin >> h >> n >> k;

    for(int i = 0;i < n;i ++)
    {
        int add , da , next;
        cin >> add >> da >> next;

        d[add] = da;
        ne[add] = next;
    }

    int cnt = 0;
    int q[N];
    for(int i = h;i != -1;i = ne[i])
    {
        q[cnt] = i;
        cnt ++;
    }

    //整体翻转 
    reverse(q,q+cnt);

    //区域翻转 
    for(int i = cnt - 1; i >= 0;i -= k)
    {
        reverse(q+max(0,i-k+1),q+i+1);
    }

    for(int i = 0;i < cnt;i ++)
    {
        printf("%05d %d",q[i],d[q[i]]);
        if(i == cnt - 1)    printf(" -1\n");
        else printf(" %05d\n",q[i+1]);
    }

    return 0;
}

峰会【2022.07.12】

点击查看题目

题目链接

链接

题目描述

峰会是国家元首或政府首脑的会议。

为峰会安排休息区可不是一件简单的工作。

一共有 N 个首脑参加峰会,编号 1∼N。

这些首脑之间存在 M 对两两之间的直接朋友关系。

在划分区域时,我们希望被安排在同一休息区域的首脑们满足,任意两人之间都是直接朋友关系。

现在,给定 K 个关于划分休息区域的安排,请你依次判断每个安排是否合理。

输入格式

第一行包含两个整数 N 和 M。

接下来 M 行,每行包含两个整数 a,b,表示首脑 a 和首脑 b 之间存在直接朋友关系。

再一行包含整数 K。

接下来 K 行,每行描述一个区域安排,首先包含一个整数 L,表示该安排打算将 L 个首脑安排在同一区域休息,然后包含 L 个整数,表示这些首脑的编号。

输出格式

共 K 行,第 i 行输出对第 i 个安排的判断,具体格式为

如果安排满足其中的任意两人之间都是直接朋友关系并且不存在额外的人与被安排的所有人都是直接朋友关系(即无法安排更多的人在这一区域休息),则输出 Area X is OK.
如果安排满足其中的任意两人之间都是直接朋友关系并且存在额外的人与被安排的所有人都是直接朋友关系(即可以安排更多的人在这一区域休息),则输出 Area X may invite more people, such as H.,其中 H 是额外可被安排的人的编号(如果不唯一,则输出最小的那个)。
如果安排无法满足其中的任意两人之间都是直接朋友关系,则输出 Area X needs help.。
X 表示组别编号,从 1 到 K。

数据范围

1 ≤ N ≤ 200,
1 ≤ M ≤ N(N−1)/2,
1 ≤ a,b ≤ N,
a ≠ b,
1 ≤ K ≤ 100,
1 ≤ L ≤ N,
同一对直接朋友关系不会在输入中重复出现。

输入样例:

8 10
5 6
7 8
6 4
3 6
4 5
2 3
8 2
2 7
5 3
3 4
6
4 5 4 3 6
3 2 8 7
2 2 3
1 1
2 4 6
3 3 2 1

输出样例:

Area 1 is OK.
Area 2 is OK.
Area 3 is OK.
Area 4 is OK.
Area 5 may invite more people, such as 3.
Area 6 needs help.

难度:简单

时/空限制:0.4s / 64MB

来源:PAT甲级真题1166

算法标签

枚举

思路

暴力,按照题目意思,枚举解决

代码

点击查看代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

const int N  = 210;
bool g[N][N];
int st[N];
int n , m , k;

int main()
{
	cin >> n >> m;
	
	while(m --)
	{
		int a , b;
		cin >> a >> b;
		g[a][b] = g[b][a] = true;
	}
	
	cin >> k;
	for(int T = 1;T <= k;T ++)
	{
		int cnt;
		cin >> cnt;
		
		memset(st,false,sizeof(st));
		
		while(cnt --)
		{
			int x;
			cin >> x;
			st[x] = true;
		}
		
		bool is_zuixiaoshengchengshu = true;
		for(int i = 1;i <= n;i ++)
			for(int j = i+1 ;j <= n;j ++)
			{
				if(st[i] && st[j] && !g[i][j])
					is_zuixiaoshengchengshu = false;
			}
		
		if(!is_zuixiaoshengchengshu)
			printf("Area %d needs help.\n",T);
		else
		{
			int id = 0;
			
			for(int i = 1;i <= n;i ++)
			{
				if(!st[i])//如果不在集合内 
				{
					bool all = true;
					for(int j = 1;j <= n;j ++)
					{
						if(st[j] && !g[i][j])
						{
							all = false;
							break;
						}
					}
					
					if(all)
					{
						id = i;
						break;
					}
				}
			}
			
			if(id)
				printf("Area %d may invite more people, such as %d.\n",T,id);
			else
				printf("Area %d is OK.\n",T);			
		}
	}
		
	return 0;
}

放苹果【2022.07.12】

点击查看题目

原题链接

链接

题目描述

把 M 个同样的苹果放在 N 个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?

盘子相对顺序不同,例如 5,1,1 和 1,5,1 算作同一种分法。

输入格式

输入包含多组测试数据。

每组数据占一行,包含两个整数 M 和 N。

输出格式

每组数据,输出一行一个结果表示分法数量。

数据范围

1 ≤ M,N ≤ 10

输入样例:

7 3

输出样例:

8

难度:简单

时/空限制:1s / 64MB

来源:北京大学考研机试题

算法标签

DFS、DP

思路

分苹果,可以想到排列数字,用DFS

代码

点击查看代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

int m , n;

int dfs(int u , int sum , int last)
{
	if(u == n)
	{
		if(sum == 0)	return 1;//苹果分完了 
		return 0;
	}
	
	int res = 0;
	for(int i = last;i <= sum;i ++)
		res += dfs(u + 1,sum - i,i);

	return res;
}

int main()
{
	while(cin >> m >> n)
		cout << dfs(0,m,0) << endl;
		
	return 0;
}

简单排序【2022.07.13】

点击查看题目

题目链接

链接

题目描述

给定一个包含 n 个整数的数组,请你删除数组中的重复元素并将数组从小到大排序后输出。

输入格式

第一行包含一个整数 n。

第二行包含 n 个不超过 1000 的正整数。

输出格式

输出去重和排序完毕后的数组。

数据范围

1 ≤ n ≤ 1000

输入样例:

6
8 8 7 3 7 7

输出样例:

3 7 8

难度:简单

时/空限制:1s / 64MB

总通过数:1553
总尝试数:1830

来源:上海交通大学考研机试题

算法标签

排序

思路

输入数据时判断一下,该数据是否输入过,再使用sort()函数

代码

点击查看代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

const int N = 1010;
bool st[N];
int q[N];
int cnt = 0;

int main()
{
	int n ;
	cin >> n;
	
	while(n --)
	{
		int x;
		cin >> x;
		
		if(!st[x])
		{
			q[cnt] = x;
			cnt ++;
			st[x] = true;
		}
	}
	
	sort(q,q+cnt);
	
	for(int i = 0;i < cnt;i ++)
		cout << q[i] << " " ;
	
	cout << endl;
	
	return 0;
}

哈夫曼树【2022.07.13】

点击查看题目

题目链接

链接

题目描述

给定 N 个权值作为 N 个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。

现在,给定 N 个叶子结点的信息,请你构造哈夫曼树,并输出该树的带权路径长度。

相关知识:

1、路径和路径长度

在一棵树中,从一个结点往下可以达到的孩子或孙子结点之间的通路,称为路径。通路中分支的数目称为路径长度。若规定根结点的层数为 1,则从根结点到第 L 层结点的路径长度为 L−1。

2、结点的权及带权路径长度

若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积。

3、树的带权路径长度

树的带权路径长度规定为所有叶子结点的带权路径长度之和,记为 WPL。

输入格式

第一行包含整数 N,表示叶子结点数量。

第二行包含 N 个整数,表示每个叶子结点的权值。

输出格式

输出一个整数,表示生成哈夫曼树的带权路径长度。

数据范围

2 ≤ N ≤ 1000,
叶子结点的权值范围 [1,100]。

输入样例:

5
1 2 2 5 9

输出样例:

37

难度:简单

时/空限制:1s / 64MB

来源:北京邮电大学考研机试题

算法标签

huffman树、贪心堆

思路

创建优先队列,存放时采取从小到大(greater()类,需要头文件#include <functional>)
优先队列定义为:priority_queue<int,vector<int>,greater<int>> q;
什么是哈夫曼树?
牛客链接

代码

点击查看代码
#include <iostream>
#include <cstring>
#include <cstring>
#include <cmath> 
#include <algorithm>
#include <queue>
#include <functional>

using namespace std;

int main()
{
	int n;
	cin >> n;
	
	priority_queue<int,vector<int>,greater<int>> q;
	
	for(int i = 0;i < n;i ++)
	{
		int x;
		cin >> x;
		q.push(x);
	}
	
	int res = 0;
	while(q.size() > 1)
	{
		int x = q.top();
		q.pop();
		int y = q.top();
		q.pop();
		
		int sum = x + y;
		res += sum;
		
		q.push(sum);
	}
	
	
	cout << res << endl;
	return 0;
}

数制转换【2022.07.13】

点击查看题目

题目链接

链接

题目描述

求任意两个不同进制非负整数的转换(2 进制 ∼ 16 进制),所给整数在 int 范围内。

不同进制的表示符号为(0,1,…,9,a,b,…,f)或者(0,1,…,9,A,B,…,F)

输入格式

输入只有一行,包含三个整数 a,n,b。a 表示其后的 n 是 a 进制整数,b 表示欲将 a 进制整数 n 转换成 b 进制整数。

a,b 是十进制整数。

数据可能存在包含前导零的情况。

输出格式

输出包含一行,该行有一个整数为转换后的 b 进制数。

输出时字母符号全部用大写表示,即(0,1,…,9,A,B,…,F)。

数据范围

2 ≤ a,b ≤ 16,
给定的 a 进制整数 n 在十进制下的取值范围是 [1,2147483647]。

输入样例:

15 Aab3 7

输出样例:

```210306``

难度:简单

时/空限制:1s / 64MB

来源:北京大学考研机试题

算法标签

进位制

思路

将 输入的a进制的数,先转化为10进制,再转换为b进制
利用短除法

代码

点击查看代码
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <algorithm>

using namespace std;

int char_to_int(char n)
{
	if(n <= '9') return n-'0';
	if(n <= 'Z') return n-'A'+10;
	return n-'a'+10;
}

char int_to_char(int n)
{
	if(n < 10) return '0'+n;
	
	return 'A'+n-10;
}

int main()
{
	int x , y;
	string num;
	
	cin >> x >> num >> y;
	
	int n = 0;
	for(auto z : num)
	{
		n = n * x +char_to_int(z);
	}
	
	string res;
	while(n)
	{
		res += int_to_char(n % y);
		n /= y;
	}
	
	reverse(res.begin(),res.end());
	
	cout << res << endl;
	return 0;
}

树查找 【2022.07.14】

点击查看题目

题目链接

链接

题目描述

给定一棵包含 n 个结点(编号 1∼n)的完全二叉树的层序遍历序列,请按照从左到右的顺序输出该树第 k 层的全部结点编号。

输入格式

第一行包含整数 n。

第二行包含 n 个整数,表示该二叉树的层序遍历序列。

第三行包含整数 k。

输出格式

共一行,按照从左到右的顺序输出该树第 k 层的全部结点编号。

数与数之间用单个空格隔开。

若无该层结点,则输出 EMPTY。

数据范围

1 ≤ n ≤ 1000,
1 ≤ k ≤ 20

输入样例:

4
1 2 3 4
2

输出样例:

2 3

难度:简单

时/空限制:1s / 64MB

来源:北京邮电大学考研机试题

算法标签

树、找规律

代码思路

模拟,不需要建树!只需要找出其中的规律就行
k表示层数
image

代码

点击查看代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

const int N = 1010;
int n;
int node[N];

int qmi(int a,int b)
{
	int res = 1;
	while(b)
	{
		if(b % 2 == 1) res = res *a;
		
		a = a*a;
		b /= 2;
	}
	
	return res;
}

int main()
{
	cin >> n;
	for(int i = 1;i <= n;i ++)
		cin >> node[i];
	
	int k;
	cin >> k;
	
	int start = qmi(2,k-1);
	int end = qmi(2,k) - 1;
	
	for(int i = start;i <= end && i <= n;i ++)
	{
		cout << node[i] << ' ';	
	}
	
	if(start >= n) puts("EMPTY");
	
	return 0;
}

日期类【2022.07.14】

点击查看题目

题目链接

https://www.acwing.com/problem/content/3567/

题目描述

编写一个日期类,要求按 xxxx-xx-xx 的格式输出日期,实现加一天的操作。

输入格式

第一行包含整数 T,表示共有 T 组测试数据。

每组数据占一行,包含 3 个用空格隔开的整数,分别表示年月日。

输出格式

每组数据输出一行,一个结果,按 xxxx-xx-xx 的格式输出,表示输入日期的后一天的日期。

数据范围

输入日期保证合法且不会出现闰年。
年份范围 [1000,3000]

输入样例:

2
1999 10 20
2001 1 31

输出样例:

1999-10-21
2001-02-01

难度:简单

时/空限制:1s / 64MB

来源:北京理工大学考研机试题

算法标签

模拟

代码思路

模拟,题目要求是不需要判断闰年,直接日期+1,判断,月份+1,判断

代码

点击查看代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

void solve()
{
	int year , mon , data;
	cin >> year >> mon >> data;
	
	if(mon == 2)
	{
		if(data == 28)
		{
			data = 1;
			mon ++;	
		}
		else data++;
	}
	else if(mon == 4|| mon == 6|| mon == 9|| mon == 11)
	{
		if(data == 30)
		{
			data = 1;
			mon ++;	
		}
		else data++;
	}
	else
	{
		if(data == 31)
		{
			data = 1;
			mon ++;	
		}
		else data++;
	}
	
	if(mon == 13)
	{
		year ++;
		mon = 1;
	}
	
	printf("%d-",year);
	
	if(mon < 10)
		printf("0%d-",mon);
	else
		printf("%d-",mon);
	
	if(data < 10)
		printf("0%d\n",data);
	else
		printf("%d\n",data);
}

int main()
{
	int t;
	cin >> t;
	
	while(t --)
		solve();
	
	return 0;
}

幂次方【2022.07.14】

点击查看题目

题目链接

链接

题目描述

对任意正整数 N,计算 XNmod233333 的值。

输入格式

共一行,两个整数 X 和 N。

输出格式

共一行,一个整数,表示 XNmod233333 的值。

数据范围

1 ≤ X,N ≤ 10^9

输入样例:

2 5

输出样例:

32

难度:简单

时/空限制:1s / 64MB

总通过数:1063
总尝试数:1869

来源:贵州大学考研机试题

算法标签

快速幂

代码思路

快速幂板子

代码

点击查看代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

typedef long long ll;

const ll MOD = 233333;

ll qmi(ll a,ll b,ll MOD)
{
	ll res = 1;
	while(b)
	{
		if(b % 2 == 1) res = res * a % MOD;
		
		a = a*a % MOD;
		b /= 2;
	}
	
	return res;
}

int main()
{
	ll x , n;
	cin >> x >> n;
	
	cout << qmi(x,n,MOD) << endl;
	
	return 0;
}
posted @ 2022-07-14 19:30  HeyStar  阅读(155)  评论(0)    收藏  举报