Featured image of post 题解 P1603 斯诺登的密码

题解 P1603 斯诺登的密码

更新日志:修改了一些小细节

题面来自洛谷,根据我的个人喜好有小修改

题目背景

根据斯诺登事件出的一道水题

题目描述

2013 年 X 月 X 日,俄罗斯办理了斯诺登的护照,于是他混迹于一架开往委内瑞拉的飞机。但是,这件事情太不周密了,因为 FBI 的间谍早已获悉他的具体位置——但这不是最重要的——最重要的是如果要去委内瑞拉,那么就要经过古巴,而经过古巴的路在美国的掌控之中。

丧心病狂的奥巴马迫降斯诺登的飞机,搜查时却发现,斯诺登杳无踪迹。但是,在据说是斯诺登的座位上,发现了一张纸条。纸条由纯英文构成:Obama is a two five zero.(以 . 结束输出,只有 6 个单词+一个句号,句子开头如没有大写亦为合法)这句话虽然有点无厘头,但是警官陈珺骛发现这是一条极其重要的线索。他在斯诺登截获的一台笔记本中找到了一个 C++ 程序,输入这条句子后立马给出了相对应的密码。陈珺鹜高兴得晕了过去,身为警官的你把字条和程序带上了飞机,准备飞往曼哈顿国际机场,但是在飞机上检查的时候发现——程序被粉碎了!飞机抵达华盛顿只剩5分钟,你必须在这 5 分钟内编写(杜撰)一个程序,免受上司的 10000000000%10 大板。破译密码的步骤如下:

(1)找出句子中所有用英文表示的数字($\leq 20$),列举在下:

正规:one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty

非正规:a both another first second third。为避免造成歧义,another 算作 $1$ 处理。

(2)将这些数字平方后对 $100$ 取模,如 $00,05,11,19,86,99$。

(3)把这些两位数按数位排成一行,组成一个新数,如果开头为 $0$,就去 $0$。

(4)找出所有排列方法中最小的一个数,即为密码。

// 数据已经修正 By absi2011 如果还有问题请联系我

输入格式

一个含有 6 个单词的句子。

输出格式

一个整型变量(密码)。如果没有符合要求的数字出现,则输出 0。

输入输出样例

输入 #1

1
Black Obama is two five zero .

输出 #1

1
425

分析

数据咋骂人呢

先一个个输入单词与题目给出的 26 个单词匹配,string 类型可以直接使用逻辑运算符 == 进行判断(C++ 选手谁闲着没事用 char 数组啊);

由于已经知道单词数量是 $6$ 个并不需要用到 while 循环(输入字符串的情况下 cin 的返回值情况我也不清楚)

一些问题

为什么样例输出不是 245 或者 254

25和4组成的最小数不是254吗,为什么样例给的425?

Black Obama is two five zero .

zero 是不算数的!

因此我们从六个单词中只能提取出两个:twofive

转换成数字就是 $2$ 和 $5$。

然后我们算出它们的平方。

$2^2=4$

$5^5=25$

对 $100$ 取模后结果是 $04$ 和 $25$,因为题目说

把这些 两位数 按数位排成一行

并且给出了 00,05 这两个例子

有两种排列方法,因为 $0425$ 开头为 $0$,去掉开头的 $0$ 之后就是 $425$,比另一个排列 $2504$ 小

所以这个所有排列方法中最小的一个数是 $425$,而不是 $2504$。

把这些两位数按数位排成一行,组成一个新数

我感觉中间那三个字是多余的…不仅不能帮助理解反而可能误导选手

只能得 20 分?

放一下我下载的测试点#2 的数据(请勿用于打表):

1
You are a three eight pig .
1
10964

我得了 20 分的程序在这个测试点上给出的答案是 1964,也就是忽略了所有 0,但实际上只能忽略开头那个。

如果开头为 0,就去 0。

记得排序。

1
2
3
4
5
if(num[0]) cout<<num[0];
for(int i=1;i<cnt;i++){
    if(num[i]>10) cout<<num[i];
    else cout<<'0'<<num[i];
}

忘了没有任何单词匹配的情况

可能就我没看清题?

直接输出 0 后结束程序即可。

其实不结束也啥都输出不出来,浪费点时间而已。

1
if(!cnt) cout<<0,exit(0);
冷知识,虽然 return 0; 不能写在逗号后面用于结束程序(无法通过编译),但是 exit(0); 可以

完整代码

仅供学习参考使用

抄袭、复制题解,以达到刷 AC 率/AC 数量或其他目的的行为,在洛谷是严格禁止的。

洛谷非常重视学术诚信。此类行为将会导致您成为作弊者。 具体细则请查看洛谷社区规则

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include<bits/stdc++.h>
using namespace std;
string tmp,dic[27]={"","one","two","three","four","five",//并不会出现zero 
"six","seven","eight","nine","ten",//但是这里我为了前20个数下标对应数值把0空着
"eleven","twelve","thirteen","fourteen","fifteen",
"sixteen","seventeen","eighteen","nineteen","twenty",
"a","both","another","first","second","third"};
int num[6],cnt;
int main(){
    for(int i=0;i<6;i++){
        cin>>tmp;
        if(!i&&tmp[0]>='A'&&tmp[0]<='Z') tmp[0]+='a'-'A';
        for(int j=1;j<=26;j++){
            if(tmp==dic[j]){
                if(j<=20){			//在下标1-20匹配即对应1-20 
                    num[cnt++]=j;
                    break;
                } else {
                    switch(j){
                    case 21: case 23: case 24:	//21、23、24对应1 
                        num[cnt++]=1;break;
                    case 22: case 25:		//22、25对应2 
                        num[cnt++]=2;break;
                    case 26:			//26对应3
                        num[cnt++]=3;break;
                    }
                    break;//switch 语句内的 break 仅能跳出 switch 而对外面的循环没有影响,
                    //因此必须在跳出 switch 后再 break 一次以确保跳出循环(其实继续遍历应该
                    //也没事,不会成功匹配只是浪费点时间)
                }
            }
        }
    }
    if(!cnt) cout<<0,exit(0);//冷知识,虽然 return 0 不能写在逗号后面用于结束程序但是
			     // exit(0) 可以
    for(int i=0;i<cnt;i++){
        num[i]=num[i]*num[i];
        num[i]%=100;
    }
    sort(num,num+cnt);
    if(num[0]) cout<<num[0];
    for(int i=1;i<cnt;i++){
        if(num[i]>10){
            cout<<num[i];
        } else {
            cout<<'0'<<num[i];
        }
    }
}

编辑记录

修复了最后一个解释不通的地方

2023-10-28 11:37:00

修复数学公式渲染

2021-08-06 18:39:00

暂时移除的段落:

我得了 20 分(过了测试点#1)之后重读题面的理解是把数字的每一位拆分排序,而这个帖子楼主的想法则是 254 的两种组合 425254254 更小。

未经许可禁止任意形式的商业或非商业转载。
最后更新于 Oct 19, 2021 22:53 UTC
点击这里在 Feeds Pub 上订阅本站
主站由 Vercel 驱动,如遇主站无法访问请尝试访问这些镜像:GitHub PagesCloudflare PagesNetlify(应该能实时同步)。
由于静态站点 + Serverless 部署的局限性,我引入了 Google Analytics 来收集访问数据;这些数据只是我自己看着玩的,不会被泄露;
您大可屏蔽它的 Cookie,这不会影响您浏览本站的所有内容或发表评论。
本站通过 Cloudflare Proxy 支持 IPv6 访问,但有时 Proxy 导致证书无法更新等问题时可能会关闭,届时请尝试访问镜像。
萌ICP备 20213003号
Built with Hugo
主题 StackJimmy 设计