CSP-J模拟赛三补题报告

前言

挂了110pts(

⇑ \Uparrow ⇑
\hspace{14em} 有史以来最大傻逼

T1: 100 p t s \color{green}100pts 100pts

T2: 100 p t s → 80 p t s \color{green}100pts\color{yellow}\rightarrow\color{red}80pts 100pts→80pts

T3: 100 p t s → 10 p t s \color{green}100pts\color{yellow}\rightarrow\color{red}10pts 100pts→10pts

T4: 10 p t s \color{red}10pts 10pts

T1 IP地址(ip)

5min秒了,10min检查。

题main

时间限制:1秒 内存限制:256M

【题目描述】

IP 地址(Internet Protocol Address)是互联网上用于识别和定位设备的数字标识。它是一种由32位或 128 位二进制数字组成的地址,在IPv4和IPv6两个主要版本中使用。

IP地址的主要功能是标识和寻址设备,使其能够在互联网上进行通信。通过将IP地址分配给计算机、服务器、路由器和其他网络设备,数据包可以被正确地发送到目标设备。IP地址还用于确定网络中不同设备的位置,以便进行网络管理和故障排除。

总之,IP地址是互联网上用于标识和定位设备的数字标识,使设备能够在互联网上进行通信。IP地址的外观根据其版本而有所不同。以下是IPv4和IPv6两个主要版本的IP地址中IPv4地址示例:

192.168.0.1
172.16.254.1
10.0.0.1
208.75.57.100

接下来,我们有 N N N 个设备,每个设备都有它的名称和 IPv4 地址,现在我们有 Q Q Q 个问题,每次我们想知道给出的IPv4地址是哪一个设备?

【输入格式】

第一行,一个正整数 N N N ,表示有 N N N 个设备;

接下去 N N N 行,首先输入该设备的名称,数据保证该设备的名称只由英文大小写组成,其次再输入该设备的IPv4地址;

接下去一行,输入一个正整数 Q Q Q ,表示有 Q Q Q 次询问;

接下去 Q Q Q 行,每行一个 IPv4 地址。

【输出格式】

对于 Q Q Q 次询问,每次询问输出该IPv4 地址对应的设备名称。

【输入样例 1】

4
Main 192.168.0.1
caixukun 8.8.8.8
some 123.13.34.45
other 23.32.45.54
3
192.168.0.1
23.32.45.54
8.8.8.8

【输出样例1】

Main
other
Google

【数据范围】

对于 30% 数据, 1 ≤ N , M ≤ 100 1≤N,M≤100 1≤N,M≤100;

对于 100% 数据,1≤N,M≤1000,设备的名称是只由大小写字母组成的长度小于等于100的字符串, I P v 4 IPv4 IPv4地址"a.b.c.d"满足 0 ≤ a , b , c , d ≤ 255 0≤a,b,c,d≤255 0≤a,b,c,d≤255 。

思路

用map,秒了

也可以打暴力

关于 map 的用法,详见这个。

AC Code

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
map<string,string>mp;
int main()
{
	freopen("ip.in","r",stdin);
	freopen("ip.out","w",stdout);
	int n,q;
	string ipv4,dis;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		cin>>dis>>ipv4;
		mp[ipv4]=dis;
	}
	scanf("%d",&q);
	for(int i=1;i<=q;i++)
	{
		cin>>ipv4;
		cout<<mp[ipv4]<<"\n";
	}
	return 0;
} 

T2 是否同构(same)

题main

时间限制:1秒 内存限制:256M

【题目描述】

有两个长度为 N N N 的数组 a , b a,b a,b,我们想知道数组 a a a 和数组 b b b 是否是同构数组?

我们定义两个数组 a , b a,b a,b 同构,则存在一个整数 k k k,使得 0 ≤ k ≤ ⌊ n ÷ 2 ⌋ 0≤k≤⌊n\div2⌋ 0≤k≤⌊n÷2⌋ ,有保持数组 b 不动的时候,交换数组 a a a 的前 k k k 项和后 k k k 项交换位置,即 :
s w a p ( a 1 , a N − k + 1 ) , ⋯ , s w a p ( a k , a N ) swap(a_1,a_N−k+1),⋯,swap(ak,aN) swap(a1,aN−k+1),⋯,swap(ak,aN)​​ ,使得新的数组 a a a 完全相等于数组 b b b。

【输入格式】

第一行输入一个正整数 T T T,表示有 T T T 组输入;

每组输入的第一行,输入一个正整数 N N N ;

第二行输入 N N N 个整数,表示数组 a a a;

第三行输入 N N N 个整数,表示数组 b b b。

【输出格式】

如果数组 a a a 和数组 b b b 同构,则输出 Yes ,否则,输出 No。

【输入样例 1】

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

【输出样例 1】

Yes
No
Yes

【数据范围与约定】

对于 30% 的数据有, 1 ≤ N ≤ 10 1≤N≤10 1≤N≤10。

对于 100% 的数据有, 1 ≤ T ≤ 10 1≤T≤10 1≤T≤10; 1 ≤ N ≤ 1 0 6 1≤N≤10^6 1≤N≤106 1 ≤ a i , b i ≤ N 1≤a_i,b_i ≤N 1≤ai,bi≤N,且有 a i ≠ a j ( i ≠ j ) a_i≠a_j(i≠j) ai=aj(i=j)。

思路

AC Code

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int a[1000005],b[1000005];
int main()
{
	//freopen("same.in","r",stdin);
	//freopen("same.out","w",stdout);
	int n,T;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
		}
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&b[i]);
		}
		int weizhi=n>>1+1;
		for(;weizhi<=n;weizhi++)
		{
			if(b[1]==a[weizhi])
			{
				break;
			}
		} 
		int k=n-weizhi+1;
		for(int i=1;i<=k;i++)
		{
			swap(a[i],a[n-k+i]);
		}                                           
		bool flag=1;
		for(int i=1;i<=n;i++)
		{
			if(a[i]!=b[i])
			{
				flag=0;
				break;
			}
		}
		if(flag)
		{
			printf("Yes\n");
		}
		else
		{
			printf("No\n");
		}
	}
	return 0;
}

对于一个字符,必定只有一个 k k k合法。

找到这个 k k k模拟一次,看 a , b a,b a,b是否相等。

T3 箱子(box)

思路

时间限制:1秒 内存限制:256M

【题目描述】

我们有 N N N 个箱子,每个箱子有自己的重量 w i w_i wi ,每次我们可以将至多 M M M 个箱子合并成一个重量为这几个箱子重量和的箱子,花费的体力是这合并的几个箱子的重量和。请问我们将这所有的箱子合并成一个箱子所需要花费的最少体力是多少?

【输入格式】

第一行,两个正整数 N , M N ,M N,M ,表示有 N N N 个箱子,每次操作至多可以合并 M M M 个箱子。

第二行, N N N 个正整数,表示这 N N N 个箱子每个箱子的重量。

【输出格式】

输出一个正整数,表示我们最少需要花费的体力是多少。

【输入样例 1】

3 2
1 2 3

【输出样例 1】

9

【输入样例 2】

7 3
1 2 3 4 5 6 7

【输出样例 2】

49

【输入样例 3】

3 3
1 2 3

【输出样例 3】

6

【数据范围】

对于 30% 的数据, 2 ≤ M ≤ N ≤ 1 0 3 2≤M≤N≤10^3 2≤M≤N≤103 。

对于 100% 的数据, 2 ≤ M ≤ N ≤ 1 0 5 2≤M≤N≤10^5 2≤M≤N≤105,每个箱子的重量 1 ≤ w i ≤ 1 0 6 1≤wi ≤10^6 1≤wi≤106​​ 。

思路

不足 M M M的用0补上

然后合并果子

AC Code

cpp 复制代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
priority_queue<long long>q;
int main()
{
	//freopen("box.in","r",stdin);
    //freopen("box.out","w",stdout);
	long long n,ans=0,m;
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=n;i++)
	{
		long long t;
		scanf("%lld",&t);
		q.push(-t);
	}
	if((n-1)%(m-1)>0)
	{
		int cnt=m-1-(n-1)%(m-1);
		while(cnt--)
		{
			q.push(0);
		}
}
	while(q.size()>1) 
	{
		long long cnt=0;
		for(int i=1;i<=m&&!q.empty();i++)
		{
			long long now=-q.top();
			q.pop();
			cnt+=now;
		}
		q.push(-cnt);
		ans+=cnt;
	}
	printf("%lld",ans);
	return 0;
}

T4 社恐的聚会(party)

时间限制:1秒 内存限制:256M

【题目描述】

有 N N N 个患有社交恐惧症的人想参与一个聚会,但是这个聚会只有两张桌子,这些社恐们不想跟自己不认识的人坐在一起!

你是这次聚会的主办方,请你想想办法,看看能不能将这 N N N 个人分在两张桌子,使得每张桌子的任意两个人都是相互认识的。

如果你有办法让这 N N N 个人分在两张桌子,请你再想想办法看看能不能让这两张桌子中人数最多的一张桌子的入座人数最少呢?

【输入格式】

第一行输入一个整数 N N N ,表示有 N N N 个社恐。

接下去第 2 行至第 N + 1 N+1 N+1 行,每行 N N N 个为 0 或者 1 的整数,表示第 i − 1 i−1 i−1 号人是否认识第 j j j 号人,如果为 0 ,表示第 i − 1 i−1 i−1 号社恐不认识第 j j j 号社恐,否则为 1 ,表示第 i − 1 i−1 i−1号社恐认识第 j j j 号社恐。(可以是第 i i i 号社恐认识第 j j j 号社恐,但是第 j j j 号社恐不认识第 i i i 号社恐)

【输出格式】

如果不能分成两张桌子坐下这 N N N 个人,请输出No;

否则,先输出Yes,然后再输出一个正整数,表示将这 N N N 个人安排入座之后的两张桌子中人数最多的那张入座人数最少是多少。

【输入样例 1】

3
0 1 1
1 0 1
0 1 0

【输出样例 1】

Yes
2

【输入样例 2】

3
0 0 0
0 0 0
0 0 0

【输出样例 2】

No

【输入样例 3】

4
0 1 1 1
0 0 1 1
0 1 0 1
1 0 0 0

【输出样例3】

Yes
2

【数据范围】

对于 30% 的数据, 1 ≤ N ≤ 20 1≤N≤20 1≤N≤20;

对于100% 的数据, 1 ≤ N ≤ 512 , a [ i ] [ i ] = 0 1≤N≤512, a[i][i]=0 1≤N≤512,a[i][i]=0,其中 a [ i ] [ i ] a[i][i] a[i][i] 表示第i号社恐对自己的是否认识为"不认识"。

思路

二分图判定+分组背包

AC Code

cpp 复制代码
#include<bits/stdc++.h>
#define ll long long 
using namespace std;
const int N=514;
int n,m,cnt,a[N][N],sz[N][2],col[N];
bool f[N];
bool vis[N];
bool dfs(int u,int c)
{
	vis[u]=1;
	col[u]=c;
	sz[cnt][c]++;
	for(int i=1;i<=n;i++)
	{
		if(i!=u&&(!a[i][u]||a[u][i]))
		{
			if(vis[i])
			{
				if(col[u]==col[i])
				{
					return false;
				}
			}
			else if(!dfs(i,1-c))
			{
				return false;
			}
		}
	}
	return true;
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			scanf("%d",&a[i][j]);
		}
	}
	for(int i=1;i<=n;i++)
	{
		if(!vis[i])
		{
			cnt++;
			if(!dfs(i,0))
			{
				printf("No\n");
				return 0;
			}
		}
	}
	m=n>>1;
	f[0]=1;
	for(int i=1;i<=cnt;i++)
	{
		for(int j=m;;j++)
		{
			if(j<sz[i][0]&&j<sz[i][1])
			{
				break;
			}
			if(j>=sz[i][0])
			{
				f[j]|=f[j-sz[i][0]];
			}
			if(j>=sz[i][0])
			{
				f[j]|=f[j-sz[i][1]];
			}
		}
	 } 
	for(int j=m;j>=1;j--)
	{
		if(f[j])
		{
			printf("Yes\n%d",n-j);
			break;
		}
	}
	return 0;
}
相关推荐
Ajiang282473530419 分钟前
对于C++中stack和queue的认识以及priority_queue的模拟实现
开发语言·c++
盼海23 分钟前
排序算法(五)--归并排序
数据结构·算法·排序算法
网易独家音乐人Mike Zhou4 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot
‘’林花谢了春红‘’5 小时前
C++ list (链表)容器
c++·链表·list
机器视觉知识推荐、就业指导7 小时前
C++设计模式:建造者模式(Builder) 房屋建造案例
c++
Swift社区7 小时前
LeetCode - #139 单词拆分
算法·leetcode·职场和发展
Kent_J_Truman8 小时前
greater<>() 、less<>()及运算符 < 重载在排序和堆中的使用
算法
IT 青年8 小时前
数据结构 (1)基本概念和术语
数据结构·算法
Yang.998 小时前
基于Windows系统用C++做一个点名工具
c++·windows·sql·visual studio code·sqlite3