P8597 [蓝桥杯 2013 省 B] 翻硬币个人思考总结+第五届传智杯ABC 初赛题解

18 篇文章 4 订阅
15 篇文章 0 订阅

# [蓝桥杯 2013 省 B] 翻硬币

思考:

目录

# [蓝桥杯 2013 省 B] 翻硬币​​​​​​​

思考:

# [传智杯 #5 初赛] A-莲子的软件工程学

P8870 [传智杯 #5 初赛] B-莲子的机械动力学

官方题解:

P8871 [传智杯 #5 初赛] C-莲子的排版设计学

C

题解

# [蓝桥杯 2013 省 B] 翻硬币

## 题目背景

小明正在玩一个“翻硬币”的游戏。

## 题目描述

桌上放着排成一排的若干硬币。我们用 `*` 表示正面,用 `o` 表示反面(是小写字母,不是零),比如可能情形是 `**oo***oooo`,如果同时翻转左边的两个硬币,则变为 `oooo***oooo`。现在小明的问题是:如果已知了初始状态和要达到的目标状态,每次只能同时翻转相邻的两个硬币,那么对特定的局面,最少要翻动多少次呢?

## 输入格式

两行等长字符串,分别表示初始状态和要达到的目标状态,每行长度小于 $1000$。

数据保证一定存在至少一种方案可以从初始状态和要达到的目标状态。

## 输出格式

一个整数,表示最小操作步数。

## 样例 #1

### 样例输入 #1

```
**********
o****o****
```

### 样例输出 #1

```
5
```

## 样例 #2

### 样例输入 #2

```
*o**o***o***
*o***o**o***
```

### 样例输出 #2

```
1
```

## 提示

source:蓝桥杯 2013 省 B 组 H 题

思考:

每次只能同时翻转相邻的两个硬币,想从初始状态到要达到的目标状态,可以从头到尾遍历整个字符串(可能会比较冗杂),并不会出现无解的情况。

**********
o****o****

我们模拟整个过程实验一下:当出现输入这种字符串时,我们将初始状态和要达到的目标状态进行比较可以知道分别是第1个和第6个不同,那么只需翻转(1 2)(5 6)或者(6 7)即可满足条件

*o**o***o***
*o***o**o***

比对这种输入结果可知第5个出现了不同   那么只需翻转(4 5)或者(5 6)即可满足条件

那么如何去设计整个程序呢?

#include<bits/stdc++.h>    //万能头较为方便
using namespace std;

因为输入的是字符串所以定义char类型的数组来存储

char a[1001];
char b[1001];

主函数部分可以这样想,输入两个由o*组成的字符串,取得a字符串的长度,定义一个循环变量用来遍历整个a数组,通过a数组与b数组的比较可知哪里不同,那么直接替换即可,最后在循环中用i变量来计数

int main(){
    cin>>a>>b;
    int len=strlen(a);
    int i=0,sum=0;
    while(i<len){
        if(a[i]!=b[i]){
        	a[i+1]=(a[i+1]=='*'?'o':'*');
            sum++;
        }
        i++;
    }
    cout<<sum;
    return 0;
}

没有理解第 13 行的小伙伴继续往下看:

a?b:ca?b:c 表示:

传智杯官方题解:题解 【第五届传智杯 初赛】 - kkksc03 的博客 - 洛谷博客 (luogu.com.cn)

# [传智杯 #5 初赛] A-莲子的软件工程学

## 题目背景

在宇宙射线的轰击下,莲子电脑里的一些她自己预定义的函数被损坏了。

对于一名理科生来说,各种软件在学习和研究中是非常重要的。为了尽快恢复她电脑上的软件的正常使用,她需要尽快地重新编写这么一些函数。

## 题目描述

具体而言,给定两个整数 $a,b$,保证 $b\neq 0$。莲子要实现这样一个函数 $\operatorname{fun}(a,b)$ 来将 $b$ 的符号转移到 $a$ 上。

具体而言,$\operatorname{fun}(a,b)=\operatorname{sgn}(b)\times |a|$。其中,$\operatorname{sgn}(b)=\begin{cases}1&b>0\\-1&b<0\end{cases}$

换而言之:

- 如果 $b$ 是正数,那么 $\operatorname{fun}(a,b)=+|a|=|a|$;
- 如果 $b$ 是负数,那么 $\operatorname{fun}(a,b)=-|a|$。

## 输入格式

- 共一行两个整数 $a,b$。

## 输出格式

- 共一行一个整数 $\operatorname{fun}(a,b)$ 的值。

 

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int a,b;
    cin >> a >> b;
    if (b>0 && a==INT_MIN)    // 在c/c++中,int 类型的取值范围为 [ -2147483648, 2147483647] ,超过这个范围则会产生溢出问题
        cout << 2147483648ll << endl;
    else
    {
        a=abs(a);       //求整数的绝对值
        if (b<0)
            a*=-1;
        cout << a << endl;
    }
    return 0;
}

P8870 [传智杯 #5 初赛] B-莲子的机械动力学

 不用看前面复杂的机械结构,直接看后面即可。按照题目要求输入整数 a,b,模拟这个奇怪的进位规则即可

  • 题目的坑点?主要是细节部分。例如 0+0=00+0=0 这个 00 也是有 11 的长度的,以及要考虑进位后总位数达到了 \max(n,m)+1max(n,m)+1。

(比赛的时候确实没想到这点wwwwwwww!)

比赛的时候想的是定义两个a,b数组来承接数据

然后利用两个循环来表示进制关系

官方题解:

#include <bits/stdc++.h>
using namespace std;
int a[200050],b[200050];
int main()
{
    auto read=([&]{
        int x;cin >> x;
        return x;
    });
    int n=read(),m=read();
    int len=max(n,m)+1;
    generate_n(a+1,n,read);
    generate_n(b+1,m,read);
    reverse(a+1,a+n+1);
    reverse(b+1,b+m+1);
    for (int i=1;i<=len;i++)
    {
        a[i]+=b[i];
        a[i+1]+=(a[i]/(i+1));
        a[i]%=(i+1);
    }
    while (a[len]==0 && len>1)
        len--;
    reverse(a+1,a+len+1);
    for (int i=1;i<=len;i++)
        cout << a[i] << " ";
    return 0;
}

P8871 [传智杯 #5 初赛] C-莲子的排版设计学

你现在不能休息,周围有 deadline 在游荡。     //细思极恐啊!

参考官方题解:

C

题解

读入题。暴风吸入输入数据里给定的所有字符,存到数组里,统计有多少个换行符,确定输入文件的总行数 mm。由此计算出最后一个行号的长度 s=\lfloor\lg m+1\rfloors=⌊lgm+1⌋(数学库里可以直接调用 \lglg,当然你也可以随便用什么途径算出每个数的长度)。

然后就是模拟了。对于第 ii 行,

  • 计算出 ii 的长度 t=\lfloor\lg i+1\rfloort=⌊lgi+1⌋。
  • 输出 s-ts−t 个空格,再输出 ii,然后输出 11 个空格。
  • 从第 i-1i−1 个换行的位置开始,一直到第 ii 个换行,把中间的字符全部输出。这样第 ii 行就做完了。

时间复杂度为 \mathcal O(|S|)O(∣S∣),其中 |S|∣S∣ 是输入的所有字符的个数。

#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
char buf[200050];
vector <char> s[200050];
int cnt;
int get_digit(int x)
{
    int digit=1,ret=1;
    while (ret<=x)
    {
        digit++;
        ret*=10;
    }
    return digit;
}
int main()
{
    while(fgets(buf,200000,stdin)!=NULL)
    {
        cnt++;
        for (int i=0;buf[i]!='\n';i++)
            s[cnt].push_back(buf[i]);
    }
    int cnt_digit=get_digit(cnt);
    for (int i=1;i<=cnt;i++)
    {
        for (int j=1;j<=cnt_digit-get_digit(i);j++)
            putchar(' ');
        cout << i << ' ';
        for (int j=0;j<s[i].size();j++)
            putchar(s[i][j]);
        putchar('\n');
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

时雨h

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值