本次考试,傻豆AC了第一题和第三题,第四题骗了10分,总共拿了210分。
首先是第一题:IP地址(ip)
【题目描述】
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
接下来,我们有 NN 个设备,每个设备都有它的名称和IPv4地址,现在我们有 QQ 个问题,每次我们想知道给出的IPv4地址是哪一个设备?
【输入格式】
第一行,一个正整数 NN ,表示有 NN 个设备;
接下去 NN 行,首先输入该设备的名称,数据保证该设备的名称只由英文大小写组成,其次再输入该设备的IPv4地址;
接下去一行,输入一个正整数 QQ ,表示有 QQ 次询问;
接下去 QQ 行,每行一个IPv4地址。
【输出格式】
对于 QQ 次询问,每次询问输出该IPv4地址对应的设备名称。
【输入样例 1】
4 Main 192.168.0.1 Google 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
这道题傻豆觉得不是很难,稍微有点水,考试的时候就做出来了,直接用结构体+暴力枚举,一遍就AC了,下面是AC代码:
#include<iostream>
#include<string>
using namespace std;
const int N=1e3+10;
int n,q;
struct node{
string a,b,c;
}s[N];
int main(){
//freopen("ip.in","r",stdin);
//freopen("ip.out","w",stdout);
cin>>n;
for(int i=0;i<n;i++){
cin>>s[i].a>>s[i].b;
}
cin>>q;
for(int i=0;i<q;i++){
cin>>s[i].c;
}
for(int j=0;j<q;j++){
for(int i=0;i<n;i++){
if(s[i].b==s[j].c){
cout<<s[i].a<<endl;
}
}
}
//fclose(stdin);
//fclose(stdout);
return 0;
}
接下来是第二题:是否同构(same)
【题目描述】
有两个长度为 NN 的数组 a,ba,b,我们想知道数组 aa 和数组 bb 是否是同构数组?
我们定义两个数组 a,ba,b 同构,则存在一个整数 kk,使得 0≤k≤⌊N2⌋0≤k≤⌊2N⌋ ,有保持数组 bb 不动的时候,交换数组 aa 的前 kk 项和后 kk 项交换位置,即 swap(a1,aN−k+1,⋯,swap(ak,aN))swap(a1,aN−k+1,⋯,swap(ak,aN)),使得新的数组 aa 完全相等于数组 bb。
【输入格式】
第一行输入一个正整数 TT ,表示有 TT 组输入;
每组输入的第一行,输入一个正整数 NN ;
第二行输入 NN 个整数,表示数组 aa;
第三行输入 NN 个整数,表示数组 bb。
【输出格式】
如果数组 aa 和数组 bb 同构,则输出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
这道题考试的时候傻豆没有一点思路,所以直接跳过去做第三题了,赛后老师讲了以后,傻豆大概捋清了思路,先循环遍历a数组的每一个数,再找到b数组中的一样的数,看它在a数组中的位置在哪里,然后将a数组中的两个数互相交换,看看和b数组是否相同,输出Yes或No即可,下面是AC代码:
#include<iostream>
using namespace std;
const int N=1e6+10;
int t,n,a[N],b[N];
bool check(){
for(int i=1;i<=n;i++){
if(a[i]!=b[i]){
return false;
}
}
return true;
}
int main(){
//freopen("same.in","r",stdin);
//freopen("same.out","w",stdout);
cin>>t;
while(t--){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<=n;i++){
cin>>b[i];
}
if(check()){
cout<<"Yes"<<endl;
continue;
}
int pos=(n>>1)+1;
for(pos=1;pos<=n;pos++){
if(a[pos]==b[1]){
break;
}
}
for(int i=pos;i<=n;i++){
swap(a[i],a[i-pos+1]);
}
if(check()){
cout<<"Yes"<<endl;
}
else{
cout<<"No"<<endl;
}
}
//fclose(stdin);
//fclose(stdout);
return 0;
}
然后是第三题:箱子(box)
【题目描述】
我们有 NN 个箱子,每个箱子有自己的重量 wi,每次我们可以将至多 M 个箱子合并成一个重量为这几个箱子重量和的箱子,花费的体力是这合并的几个箱子的重量和。请问我们将这所有的箱子合并成一个箱子所需要花费的最少体力是多少?
【输入格式】
第一行,两个正整数 N ,M ,表示有 N个箱子,每次操作至多可以合并 M 个箱子。
第二行,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
这道题傻豆在比赛中花费了大量时间来攻克,最后拿了100分,傻豆当时看到这题,以为是D4的合并果子(洛谷P1090),于是用优先队列写了一下代码,可当傻豆试样例的时候,发现不太对,于是又读了一下题目,注意到了标红的部分,原来的题目是两两合并,现在是MM合并,于是在原来的基础上傻豆每次将n更新了一下,在加了一个m次的循环,在注意一些细节,这道题就AC了,下面是AC代码:
#include<iostream>
#include<queue>
using namespace std;
long long n,m,a,sum,cnt,x;
int main(){
//freopen("box.in","r",stdin);
//freopen("box.out","w",stdout);
priority_queue<long long>q;
cin>>n>>m;
for(long long i=1;i<=n;i++){
cin>>a;
q.push(-a);
}
while(n>m){
n-=(m-1);
}
for(long long i=1;i<=n;i++){
x=-q.top();
q.pop();
cnt+=x;
}
q.push(-cnt);
sum+=cnt;
while(q.size()>1){
cnt=0;
for(long long i=1;i<=m;i++){
if(q.empty()){
break;
}
x=-q.top();
q.pop();
cnt+=x;
}
q.push(-cnt);
sum+=cnt;
}
cout<<sum<<endl;
//fclose(stdin);
//fclose(stdout);
return 0;
}
最后是第四题:社恐的聚会(party)
【题目描述】
有 NN 个患有社交恐惧症的人想参与一个聚会,但是这个聚会只有两张桌子,这些社恐们不想跟自己不认识的人坐在一起!
你是这次聚会的主办方,请你想想办法,看看能不能将这 NN 个人分在两张桌子,使得每张桌子的任意两个人都是相互认识的。
如果你有办法让这 NN 个人分在两张桌子,请你再想想办法看看能不能让这两张桌子中人数最多的一张桌子的入座人数最少呢?
【输入格式】
第一行输入一个整数 NN ,表示有 NN 个社恐。
接下去第 22 行至第 N+1N+1 行,每行 NN 个为 00 或者 11 的整数,表示第 i−1i−1 号人是否认识第 jj 号人,如果为 00 ,表示第 i−1i−1 号社恐不认识第 jj 号社恐,否则为 11 ,表示第 i−1i−1 号社恐认识第 jj 号社恐。(可以是第 ii 号社恐认识第 jj 号社恐,但是第 jj 号社恐不认识第 ii 号社恐)
【输出格式】
如果不能分成两张桌子坐下这 NN 个人,请输出No
;
否则,先输出Yes
,然后再输出一个正整数,表示将这 NN 个人安排入座之后的两张桌子中人数最多的那张入座人数最少是多少。
【输入样例 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
这道题傻豆考试的时候没思路,于是编了一个代码,骗了10分,赛后老师说是二分图再加上分组背包,傻豆看着老师的代码,原模原样的写了出来,下面是AC代码:
#include<iostream>
#define ll long long
using namespace std;
const int N=520;
int n,m,cnt,s2[N][2],col[N],a[N][N];
bool f[N];
bool vis[N];
bool dfs(int u,int c){
vis[u]=1,col[u]=c,s2[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(){
//freopen("party.in","r",stdin);
//freopen("party.out","w",stdout);
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cin>>a[i][j];
}
}
for(int i=1;i<=n;i++){
if(!vis[i]){
cnt++;
if(!dfs(i,0)){
cout<<"No"<<endl;
return 0;
}
}
}
m=n>>1;
f[0]=1;
for(int i=1;i<=cnt;i++){
for(int j=m;j>=1;j--){
if(j<s2[i][0]&&j<s2[i][1]){
break;
}
if(j>=s2[i][0]){
f[j]|=f[j-s2[i][0]];
}
if(j>=s2[i][1]){
f[j]|=f[j-s2[i][1]];
}
}
}
for(int j=m;j>=1;j--){
if(f[j]){
cout<<"Yes"<<endl;
cout<<n-j;
break;
}
}
//fclose(stdin);
//fclose(stdout);
return 0;
}
总结:这次考试,傻豆比上次进步了200分,希望下次能再接再厉,继续保持100分以上