CSP-J模拟赛三补题报告

5 篇文章 0 订阅
4 篇文章 0 订阅

前言

挂了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 100pts80pts
T3: 100 p t s → 10 p t s \color{green}100pts\color{yellow}\rightarrow\color{red}10pts 100pts10pts
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 1N,M100

对于 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 0a,b,c,d255

思路

用map,秒了

也可以打暴力

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

AC Code

#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⌋ 0kn÷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(a​k,a​N) swap(a1,aNk+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 1N10

对于 100% 的数据有, 1 ≤ T ≤ 10 1≤T≤10 1T10 1 ≤ N ≤ 1 0 6 1≤N≤10^6 1N106 1 ≤ a ​ i , b ​ i ≤ N 1≤a​_i,b_​i ≤N 1ai,biN,且有 a i ≠ a j ( i ≠ j ) a_i≠a_j(i≠j) ai=aj(i=j)

思路

AC Code

#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 NM ,表示有 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 2MN103

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

思路

不足 M M M的用0补上
然后合并果子

AC Code

#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 i1 号人是否认识第 j j j 号人,如果为 0 ,表示第 i − 1 i−1 i1 号社恐不认识第 j j j 号社恐,否则为 1 ,表示第 i − 1 i−1 i1号社恐认识第 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 1N20
对于100% 的数据, 1 ≤ N ≤ 512 , a [ i ] [ i ] = 0 1≤N≤512, a[i][i]=0 1N512,a[i][i]=0,其中 a [ i ] [ i ] a[i][i] a[i][i] 表示第i号社恐对自己的是否认识为“不认识”。

思路

二分图判定+分组背包

AC Code

#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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值