NEFU 大一寒假2.15考试 2020.02.15

Summary

昨天的 题目预测 准确率 1/7=14.29%,也算是意料之中吧。
毕竟是个考试嘛,而且似乎可能差不多已经暴露了预测吧。

什么?你没看到昨天的题目预测?再仔细观察一下那个 peach 吧,
难道你就没有怀疑过我为啥要把它扔进 CTF 专栏吗?
我会真的发一个 peach 吗?Of course not!
好吧,如果你实在没有发现,请看本文末尾的彩蛋 ~
在这里插入图片描述
至于这个官方题解里的六花嘛。。emm…
应该不是我,估计不是我,肯定跟我没关系,嗯,就这样吧 2333…
在这里插入图片描述

Information

No.TitleAC/Submit
A机器人60/146
B纸牌游戏68/165
C咸鱼连突刺37/289
D库特的合并果子58/313
E库特的素数队列(1)32/125
F库特的素数队列(2)17/76
G库特的绳子7/57

Problem A: 机器人 (1295) [60/146]

Tips

这个题方法很多,我是把原数和倒过来的数存在结构体里排序
按倒过来之后的数排序,再输出原数即可。
这个排序正好练练优先队列的重载,直接写 cmp 也可以。

像题解那样读入字符串进行处理也是一个挺好的方法。

Code

#include <bits/stdc++.h>
using namespace std;

struct number
{
	int ori;
	int fx;
}num;

bool operator < (const number &p1,const number &p2)
{
	return p1.fx>p2.fx;
}

int main()
{
	priority_queue<number>q;
	int n,x,cnt,tmp;
	while(cin>>n)
	{
		while(n--)
		{
			cin>>x;
			num.ori=x;
			tmp=0;
			while(x>0)
			{
				tmp*=10;
				tmp+=x%10;
				x/=10;
			}
			num.fx=tmp;
			q.push(num);
		}
		while(q.size()>1)
		{
			cout<<q.top().ori<<" ";
			q.pop();
		}
		cout<<q.top().ori<<endl;
		q.pop();
	}
	return 0;
}

Problem B: 纸牌游戏 (1311) [68/165]

Tips

这个算是个简单的签到题吧,注意行尾别多打逗号即可。

Code

#include <bits/stdc++.h>
using namespace std;

int main()
{
	queue<int>q;
	int t,n;
	cin>>t;
	while(t--)
	{
		cin>>n;
		while(!q.empty())q.pop();
		for(int i=1;i<=n;i++)
		{
			q.push(i);
		}
		while(q.size()>2)
		{
			cout<<q.front()<<",";
			q.pop();
			q.push(q.front());
			q.pop();
		}
		if(q.size()>1)
		{
			cout<<q.front()<<endl;
			q.pop();
		}
		cout<<q.front()<<endl;
	}
	return 0;
}

Problem C: 咸鱼连突刺 (2114) [37/289]

Tips

这个主要考的是读题,嗯,就是读题,题看懂了就没问题了
取 L 和 R 之间最大的素数与最小的素数之和的伤害值(包括L和R)
如果 L R 之间只有一个素数,那就加它的二倍
如果 L R 之间没有素数就不加(加上 0)

Code

#include <bits/stdc++.h>
using namespace std;

const int MAXN=1e6+1;
char prime[MAXN];
int primeList[MAXN],num=0;
void getPrime()
{
    memset(prime,1,sizeof(prime));
    prime[0]=prime[1]=0;
    for(int i=2;i<MAXN;i++)
    {
        if(prime[i])primeList[num++]=i;
        for (int j=0;j<num&&i*primeList[j]<MAXN;j++)
        {
            prime[i*primeList[j]]=0;
            if(i%primeList[j]==0)break;
        }
    }
}

int main()
{
	getPrime();
	int t,l,r,pos1,pos2;
	long long sum=0;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d %d",&l,&r);
		pos1=lower_bound(primeList,primeList+num,l)-primeList;
		pos2=upper_bound(primeList,primeList+num,r)-primeList-1;
		if(pos1<num&&primeList[pos1]>r||pos2>=0&&primeList[pos2]<l);
		else sum+=primeList[pos1]+primeList[pos2];
	}
	printf("%lld\n",sum);
	return 0;
}

Problem D: 库特的合并果子 (2110) [58/313]

Tips

这个就直接在昨天那个三题通杀代码的基础上改就可以了。
主要改动就是把输出总和改成输出过程了,
还要注意处理一下每组数据行尾的空格,不要多打印空格。

Code

#include <bits/stdc++.h>
using namespace std;

int main()
{
	priority_queue<long long,vector<long long>,greater<long long> >q;
	long long tmp,n;
	while(cin>>n)
	{
		while(!q.empty())q.pop();
		while(n--)
		{
			cin>>tmp;
			q.push(tmp);
		}
		while(q.size()!=1)
		{
			tmp=q.top();
			q.pop();
			tmp+=q.top();
			q.pop();
			q.push(tmp);
			if(q.size()!=1)cout<<tmp<<" ";
		}
		cout<<tmp<<endl;
	}
	return 0;
}

Problem E: 库特的素数队列(1) (2111) [32/125]

Tips

T ≤ 3 这个范围好啊,直接用队列模拟就可以了。

Code

#include <bits/stdc++.h>
using namespace std;

const int MAXN=1e7+1;
char prime[MAXN];
int primeList[MAXN],num=0;
void getPrime()
{
    memset(prime,1,sizeof(prime));
    prime[0]=prime[1]=0;
    for(int i=2;i<MAXN;i++)
    {
        if(prime[i])primeList[num++]=i;
        for (int j=0;j<num&&i*primeList[j]<MAXN;j++)
        {
            prime[i*primeList[j]]=0;
            if(i%primeList[j]==0)break;
        }
    }
}

int main()
{
	queue<int>q;
	getPrime();
	int t,n,cnt,qs;
	cin>>t;
	while(t--)
	{
		cin>>n;
		for(int i=1;i<=n;i++)q.push(i);
		while(q.size()!=1)
		{
			qs=q.size();
			for(int i=1;i<=qs;i++)
			{
				if(q.size()==1)break;
				if(prime[i])q.push(q.front());
				q.pop();
			}
		}
		cout<<q.front()<<endl;
		q.pop();
	}
	return 0;
}

Problem F: 库特的素数队列(2) (2112) [17/76]

Tips

T ≤ 30000 这个范围就有点吓人了,本地跑都没停下来。
那就找找规律吧,正好用上面 E 题打个表试试。
不用都打出来,打一会就看出规律了,很容易看出来。
在这里插入图片描述
总共也没几组,暴力 if 都没啥问题。
我放在程序里现打的,也确实没多少。
在这里插入图片描述

Code

#include <bits/stdc++.h>
using namespace std;

const int MAXN=1e7+1;
char prime[MAXN];
int primeList[MAXN],num=0;
void getPrime()
{
    memset(prime,1,sizeof(prime));
    prime[0]=prime[1]=0;
    for(int i=2;i<MAXN;i++)
    {
        if(prime[i])primeList[num++]=i;
        for (int j=0;j<num&&i*primeList[j]<MAXN;j++)
        {
            prime[i*primeList[j]]=0;
            if(i%primeList[j]==0)break;
        }
    }
}

int anstab[MAXN],an=0;
void getAns()
{
	for(int i=1;i<num;)
	{
		i=anstab[an++]=primeList[i-1];
	}
}

int main()
{
	ios::sync_with_stdio(0);
	getPrime();
	getAns();
	int t,n,cnt,qs,pos;
	cin>>t;
	while(t--)
	{
		cin>>n;
		if(n==1)
		{
			cout<<1<<endl;
			continue;
		}
		pos=upper_bound(anstab,anstab+an,n)-anstab-1;
		cout<<anstab[pos]<<endl;
	}
	return 0;
}

Problem G: 库特的绳子 (1949) [|7/57]

Tips

这就是那个唯一预测出来的题目了,早知道就提前研究研究了,
要不然也不能 WA +TLE 错成这个样子 /(ㄒoㄒ)\~~

这题还是不太好想的,起初打算列出所有间隔,
然后再排序比较,后来一想,这800%TLE啊。
由于 两根靠近的钉子之间的间隔一定是最小的,所以先把靠近的钉子之间的间隔扔进优先队列,这样优先队列的队首一定是最短的间隔。
间隔采用结构体存储,分别存储左边的钉子,右边的钉子和间隔长度
同时对绳子进行排序,从最短的绳子开始 依次往钉子上挂。
每取出一根最短的绳子,消耗一个最短的间隔 (pop一次)
同时还要 向优先队列中插入一个向右延伸的间隔 即右端点 +1
(注意插入时要检测边界,不能越界。)
这样始终 保持优先队列中的队首是未被使用的最小间隔
当队列为空或者有绳子挂不上了,即为失败,输出 no
否则顺利挂完绳子,圆满结束即为成功,输出 yes

考试的时候人都傻了,时间越少越着急,把 m 打成 n 了还交了 3 遍,
今天真的是太菜了 /(ㄒoㄒ)\~~

Code

#include <bits/stdc++.h>
using namespace std;

struct pinlen
{
	int l,r,len;
}tmp;
bool operator < (const pinlen &p1,const pinlen &p2)
{
	return p1.len>p2.len;
}

priority_queue <pinlen>q;
const int MAXN=5e5+1;
int ppos[MAXN];
int slen[MAXN];
int main()
{
	int n,m,pts,i;
	while(~scanf("%d %d",&n,&m))
	{
		pts=0;
		while(!q.empty())q.pop();
		for(i=0;i<n;i++)scanf("%d",&ppos[i]);
		sort(ppos,ppos+n);
		for(i=0;i<n-1;i++)
		{
			tmp.l=i;
			tmp.r=i+1;
			tmp.len=ppos[i+1]-ppos[i];
			q.push(tmp);
		}
		for(i=0;i<m;i++)scanf("%d",&slen[i]);
		
		sort(slen,slen+m);
		bool flag=false;
		for(i=0;i<m;i++)
		{
			if(q.empty())break;
			tmp=q.top();
			q.pop();
			if(slen[i]<tmp.len)break;
			if(tmp.r+1<n)
			{
				tmp.r++;
				tmp.len=ppos[tmp.r]-ppos[tmp.l];
				q.push(tmp);
			}
		}
		if(i==m)printf("yes\n");
		else printf("no\n");
	}
	return 0;
}

彩蛋一枚

昨天的题目预测,你看明白了吗?

Step 1. 打开开发者选项,找到未被压缩的图片原图。
在这里插入图片描述
Step 2. 打开链接,右键保存图片,改后缀为 zip 打开。
在这里插入图片描述
剩下的我不说你也知道题目在哪里了 ヾ(≧▽≦*)o
其实我在就预料到这次预测不会准,所以随便 “皮” 了一下 ~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值