NOIP&CSP PJ 难度刷题记录
前言
本来不想写前言的(>人<;)
这只是 mjl 给我们布置的作业,并不是我自己在刷题!
不保证所有代码的正确性,它们仅仅是通过了所有数据点而已。
1.模拟板块
整体难度:红~黄(模拟不会有什么难题 ,别跟我说像猪国杀、儒略日那种)
T1 计算器的改良
AC at 2021-07-31 14:34:08.
难度:黄
解一元一次方程,就是把未知数的系数移到等号左边,常数移到等号右边,然后再除一下就可以了。
我们设置两个变量 \(l,r\),分别代表未知数系数计算后的结果和常数的计算结果。最后模拟就可以了。记得“移项变号”,而且往左移和往右移是相反的,如果写成一样了的可以像我一样在任意一边加一个负号,不影响结果。
不过这个模拟还是有些讲究的。
首先要把整个字符串分为 \(3\) 个部分:等号左边、等号和等号右边。
先遍历等号左边,如果看到数字了就把这个连续是一段数字的字符给转化为整数类型,然后再看这到底是系数还是常数;再再看正负。关于正负可以使用布尔变量来标记。
如果是系数就甩到 \(l\) 变量,是常数就甩到 \(r\) 变量。注意怎么甩,要移项变号。这时候可能要移项也有可能不移,要注意。
遇到减号,把布尔变量设为真。
遇到加号,把布尔变量设为假。(因为我们默认的系数和常数的符号是正,所以加号并没有什么用,只需要布尔变量归零就可以了)
遇到字母特判(经过数字的判断之后,这个字母就是系数为 \(±1\) 的未知数),也需移项变号。
等号右边同理。
记得存未知数的字母,别像我一样最后有一个测试点未知数只在等号右边,但是我处理那一块的时候没写存未知数字母的语句[捂脸]。
废话不多说,上代码。
Code
#include<cstdio>
#include<cstring>
char fh,a[105];
int len,h,l,r;
bool is_fu; //用来判断这个系数 or 常数是不是负数
int main(){
scanf("%s",a+1);
len=strlen(a+1);
//等号左边
for(int i=1;i<=len;i++){
int k=0;
if(a[i]=='='){
h=i+1;
is_fu=0;
break;
}else if(a[i]=='+') is_fu=0;
else if(a[i]=='-') is_fu=1;
else if(a[i]>='0'&&a[i]<='9'){
while(a[i]>='0'&&a[i]<='9'){
k=k*10+a[i]-'0';
i++;
}
i--;
if(a[i+1]>='a'&&a[i+1]<='z'||a[i+1]>='A'&&a[i+1]<='Z'){ //未知数
fh=a[i+1];
if(is_fu){
l-=k;
is_fu=0;
}else l+=k;
}else{ //数字
if(is_fu){
r-=k;
is_fu=0;
}else r+=k;
}
k=0;
}
}
//等号右边
is_fu=0;
for(int i=h;i<=len;i++){
int k=0;
if(a[i]=='+') is_fu=0;
else if(a[i]=='-') is_fu=1;
else if(a[i]>='0'&&a[i]<='9'){
while(a[i]>='0'&&a[i]<='9'){
k=k*10+a[i]-'0';
i++;
}
i--;
if(a[i+1]>='a'&&a[i+1]<='z'||a[i+1]>='A'&&a[i+1]<='Z'){ //未知数
fh=a[i+1];
if(is_fu){
l+=k;
is_fu=0;
}else l-=k;
}else{ //数字
if(is_fu){
r+=k;
is_fu=0;
}else r-=k;
}
k=0;
}
}
printf("%c=%.3lf",fh,-r*1.0/l);
return 0;
}
T2 税收与补贴问题
AC at 2021-08-06 9:44:39.
难度:黄
我寻思着这出题人语文该从小学重修叭。
大概意思就是先让你补全一个价格和购买人数关系的表,然后在价格上统一加(补贴)或减(收税)一个数,但是购买的人数不变,然后使得政府给出的这个价位获得的利润是所有价位都经过这个变化后中最大的。
实现我们可以用两个数组,一个用来输入,另一个,下标表示价格,数组里的值代表这个下标的价格所对应的人数。
这个问题有两个部分:
1.补全表格(此题最难部分)
题目有一个隐藏条件:在任意两个给定了人数的价格之间如果有没有给定人数的价格,那么中间所有没有给定人数的价格的人数都是“均匀地下降”,就是每两个价格所对应的人数差是一样的。
所以,遇到没有输入人数的价格时,就有三种情况:
这个价格小于给定人数的最大价格。
这个价格大于给定人数的最大价格。
这个价格是不合法的。(即小于成本价或者购买人数是负数)
为了避免计算不合法的价格,我们从成本价往上枚举价格,如果计算出来的人数是负数或 \(0\) 就立刻跳出循环。
思考如何计算第一种情况。假设我们已经枚举到了价格 \(=i\)。
我们需要确定这个价格两端最近的已经确定人数的价格是多少,因为我们是从小到大算,所以价格为 \(i-1\) 时的价格肯定已经算出。至于比它大的,枚举可以找出,在枚举的同时我们可以用一个 \(num\) 变量统计一下这中间价格的数量。
然后我们需要计算它对应的人数。怎么算呢?为了好理解我们把它分成两步:
第一步,算出两两价格之间的差值。
公式:\(d=\dfrac{b_{i-1}-b_R}{num}\),可以根据等差公式得出,也可以自己推(难度不大)。
其中 \(b\) 是上述提及实现方式的那个下标代表价格的数组。
第二步,根据 \(i-1\) 算出 \(i\)。
这个就很简单啦, \(b_i=b_{i-1}+d\) 即可。
然后再看看第二种情况。这个很简单,只需要在前面的基础上减去最后输入的那个数就可以了。
代码实现如下:
int l=a[0].money;
while(1){ //只要没有强制退出就一直循环
if(b[l]){ //这个价格输入中有对应,直接跳过
l++;
continue;
}
if(b[l-1]-p<=0) break; //如果这个价格不合法,退出循环
if(l<Max){ //情况一
int R=l,num=1;
while(!b[R]) R++,num++; //统计数量,找右端点
b[l]=b[l-1]-(b[l-1]-b[R])/num;
}else b[l]=b[l-1]-p; //情况二
l++;
Maxr=max(Maxr,l); //寻找合法价格的最右端点
}
Maxr--; //需要 -1,因为在此之前 l 加了 1
2.计算答案
过了难点我们就可以快乐地模拟了!
枚举补贴/收税的钱数,范围随意,能 A 就行/xyx。
大概思路就是暴力把每一个价位下补贴/收税后的利润做对比,如果政府规定的那个价格是最大的就可以输出。
比较简单(指我错了 \(10^9+7\) 遍,细节比较多 (〃>目<)),看代码理解。
for(int i=0;i<=MAXN-5;i++){
//补贴i元
int maxnum=0; //这个变量是用来统计最大的获利
for(int j=a[0].money;j<=Maxr;j++){
maxnum=max(maxnum,(j+i-a[0].money)*b[j]);
}
if(maxnum==(n+i-a[0].money)*b[n]){ //最大获利地数量等于政府规定地价格,输出结束
printf("%d",i);
return 0;
}
//收税i元
maxnum=0;
for(int j=a[0].money;j<=Maxr;j++){
maxnum=max(maxnum,(j-i-a[0].money)*b[j]);
}
if(maxnum==(n-i-a[0].money)*b[n]){
printf("-%d",i); //注意有负号
return 0;
}
}
最后加上预处理、特判等。
特别注意输入,坑死我辣<(  ̄^ ̄)-+——。
Code
#include<cstdio>
#define max(a,b) (a)>(b)?(a):(b)
const int MAXN=(int)1e5+5;
struct node{int money,num;}a[MAXN];
int Max,Maxr,n,p,tot,b[MAXN];
int main(){
//输入及预处理
scanf("%d %d %d",&n,&a[0].money,&a[0].num);
b[a[0].money]=a[0].num;
while(1){
++tot;
scanf("%d %d",&a[tot].money,&a[tot].num);
if(a[tot].money==-1&&a[tot].num==-1){
--tot;
break;
}
Max=max(Max,a[tot].money);
b[a[tot].money]=a[tot].num;
}
//test
//for(int i=a[0].money;i<=Max;i++) printf("%d %d\n",i,b[i]);
scanf("%d",&p);
//补全条件
int l=a[0].money;
while(1){
if(b[l]){
l++;
continue;
}
if(b[l-1]-p<=0) break;
if(l<Max){
int R=l,num=1;
while(!b[R]) R++,num++;
b[l]=b[l-1]-(b[l-1]-b[R])/num;
}else b[l]=b[l-1]-p;
l++;
Maxr=max(Maxr,l);
}
Maxr--;
//枚举
for(int i=0;i<=MAXN-5;i++){
//补贴i元
int maxnum=0;
for(int j=a[0].money;j<=Maxr;j++){
maxnum=max(maxnum,(j+i-a[0].money)*b[j]);
}
if(maxnum==(n+i-a[0].money)*b[n]){
printf("%d",i);
return 0;
}
//收税i元
maxnum=0;
for(int j=a[0].money;j<=Maxr;j++){
maxnum=max(maxnum,(j-i-a[0].money)*b[j]);
}
if(maxnum==(n-i-a[0].money)*b[n]){
printf("-%d",i);
return 0;
}
}
printf("NO SOLUTION");
return 0;
}
T3 乒乓球
AC at 2021-07-31 14:50:38.
难度:橙
模拟水题,按照一轮一轮枚举。注意一轮结束需要同时满足两个条件,否则不要结束。
这题坑比较多,这里列两个我错过的:
如果给出的字符串刚刚好到一轮结束,需要在后面再输出一个“0:0”(也不知道为什么);
如果第一个字符是“E”记得输出两个“0:0”。
Code
#include<cstdio>
#include<cmath>
#include<cstring>
#define max(a,b) (a)>(b)?(a):(b)
int len,tot;
char s[25],a[100005];
int main(){
while(scanf("%s",s+1)!=EOF){
len=strlen(s+1);
for(int i=1;i<=len;i++){
if(s[i]==' '||s[i]=='\n') continue;
if(s[i]=='E') goto type1;
a[++tot]=s[i];
}
}
type1:
int w,l;
if(!tot){
printf("0:0\n\n0:0");
return 0;
}
//11
for(int i=1;i<=tot;i++){
w=0,l=0;
while((w<11&&l<11||abs(w-l)<2)&&i<=tot){
w+=(a[i]=='W');
l+=(a[i]=='L');
i++;
}
i--;
if(i==tot){
printf("%d:%d\n",w,l);
if(w==11||l==11) printf("0:0\n");
break;
}else printf("%d:%d\n",w,l);
}
printf("\n");
//21
for(int i=1;i<=tot;i++){
w=0,l=0;
while((w<21&&l<21||abs(w-l)<2)&&i<=tot){
w+=(a[i]=='W');
l+=(a[i]=='L');
i++;
}
i--;
if(i==tot){
printf("%d:%d\n",w,l);
if(w==21||l==21) printf("0:0\n");
break;
}else printf("%d:%d\n",w,l);
}
return 0;
}
T4 不高兴的津津
AC at 2021-07-30 21:25:42.
难度:红
这真的没什么好说的了,模拟即可 ,有手就行。/cy
Code
#include<cstdio>
#define max(a,b) (a)>(b)?(a):(b)
int Max,ans,a,b;
int main(){
for(int i=1;i<=7;i++){
scanf("%d %d",&a,&b);
if(Max<a+b) ans=i;
Max=max(a+b,Max);
}
if(Max<=8) ans=0;
printf("%d",ans);
return 0;
}
T5 花生采摘
AC at 2021-07-31 14:12:53.
难度:橙
为什么我觉得这道题应该算这套题里面比较难的了?
首先注意一个大坑:采花生需要时间!(这个我错了很久)
然后如果您认真读题,就会发现它并不是一个 dp,而是一个不大的模拟( ̄y▽, ̄)╭ 。(因为 mjl 归类的是模拟板块,我想如果这是考场上我八成会犯这个错误)。
首先把所有花生的坐标和
判断是否能摘到
NOIP&CSP PJ 难度刷题记录的更多相关文章
- PE刷题记录
PE刷题记录 PE60 / 20%dif 这道题比较坑爹. 所有可以相连的素数可以构成一张图,建出这张图,在其中找它的大小为5的团.注意上界的估算,大概在1W以内.1W内有1229个素数,处理出这些素 ...
- leetcode刷题记录--js
leetcode刷题记录 两数之和 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但 ...
- Leetcode刷题记录(python3)
Leetcode刷题记录(python3) 顺序刷题 1~5 ---1.两数之和 ---2.两数相加 ---3. 无重复字符的最长子串 ---4.寻找两个有序数组的中位数 ---5.最长回文子串 6- ...
- 刷题记录:[HarekazeCTF2019]encode_and_encode
目录 刷题记录:[HarekazeCTF2019]encode_and_encode 一.知识点 JSON转义字符绕过 php伪协议 刷题记录:[HarekazeCTF2019]encode_and_ ...
- 刷题记录:[De1CTF 2019]Giftbox && Comment
目录 刷题记录:[De1CTF 2019]Giftbox && Comment 一.知识点 1.sql注入 && totp 2.RCE 3.源码泄露 4.敏感文件读取 ...
- 刷题记录:[强网杯 2019]Upload
目录 刷题记录:[强网杯 2019]Upload 一.知识点 1.源码泄露 2.php反序列化 刷题记录:[强网杯 2019]Upload 题目复现链接:https://buuoj.cn/challe ...
- 刷题记录:[XNUCA2019Qualifier]EasyPHP
目录 刷题记录:[XNUCA2019Qualifier]EasyPHP 解法一 1.error_log结合log_errors自定义错误日志 2.include_path设置包含路径 3.php_va ...
- 刷题记录:[DDCTF 2019]homebrew event loop
目录 刷题记录:[DDCTF 2019]homebrew event loop 知识点 1.逻辑漏洞 2.flask session解密 总结 刷题记录:[DDCTF 2019]homebrew ev ...
- 刷题记录:[CISCN2019 东北赛区 Day2 Web3]Point System
目录 刷题记录:[CISCN2019 东北赛区 Day2 Web3]Point System 知识点 1.padding-oracle attack 2.cbc字节翻转攻击 3.FFMpeg文件读取漏 ...
随机推荐
- Unity的AnimationCurve
转自:风宇冲Unity3D教程学院http://blog.sina.com.cn/s/blog_471132920101f8nv.html,本文有多处增删减改,详细内容请查看原文. 1.介绍 Anim ...
- 『无为则无心』Python序列 — 20、Python元组的介绍与使用
目录 1.元组的应用场景 2.定义元组 3.元组的常见操作 @1.按下标查找数据 @2.index()方法 @3.count()方法 @4.len()方法 4.元祖中的列表元素 5.扩展:序列封包和序 ...
- python导入模块--案例
1 导入模块 1.1 问题 本案例要求先编写一个star模块,主要要求如下: 建立工作目录 ~/bin/ 创建模块文件 ~/bin/star.py 模块中创建pstar函数,实现打印50个星号的功能 ...
- CentOS-配置JDK(压缩包)
卸载openjdk $ rpm -qa | grep jdk 以上命令用来检查linux上是否安装openjdk,如果安装需要将其全部卸载掉,卸载命令: $ rpm -e --nodeps java- ...
- gitlab hostname修改
cd /var/opt/gitlab/gitlab-rails/etc vim gitlab.yml /home/git/gitlab/config/gitlab.yml production: &a ...
- 2012年第三届蓝桥杯C/C++程序设计本科B组省赛 密码发生器
密码发生器 题目描述: ```bash 在对银行账户等重要权限设置密码的时候,我们常常遇到这样的烦恼:如果为了好记用生日吧,容易被破解,不安全:如果设置不好记的密码,又担心自己也会忘记:如果写在纸上, ...
- fast-poster海报生成器v1.4.0,一分钟完成海报开发
fast-poster海报生成器v1.4.0,一分钟完成海报开发 介绍 一个快速开发动态海报的工具 在线体验:https://poster.prodapi.cn/ v1.4.0 新特性 为了项目和团队 ...
- 使用crt连接linux慢
1.主要原因是linux中启用了 修改sshd的配置文件把其中dns解析设置为no即可,操作如下: [root@dong ~]# vi /etc/ssh/sshd_config 查找: #UseDNS ...
- Python报错“UnicodeDecodeError: 'ascii' codec can't decode byte 0xe9 in position 0: ordinal not in range(128)”的解决办法
最近在用Python处理中文字符串时,报出了如下错误: UnicodeDecodeError: 'ascii' codec can't decode byte 0xe9 in position 0: ...
- 微软商业智能系列(一)初识微软BI
随着移动互联网.云计算.物联网和大数据技术的广泛应用,社会已经迈入全新的数据时代.掌握数据资产,进行智能化决策,已成为企业胜出的关键.越来越多的企业开始重视数据战略布局,重新定义自己的核心竞争力,从数 ...