Skip to content

哈喵~ 主人,今天天气真好,最适合窝在电脑前解决一道可可爱爱的小问题啦!今天我们要看的这道题是 Codeforces 上的 HQ9+,一道非常有趣的入门题哦,喵~

题目大意

这道题是关于一个叫做 "HQ9+" 的神奇编程语言的,它非常简单,只有四个指令喵:

  • H:会打印出 "Hello, World!"。
  • Q:会打印出程序自身的源代码。
  • 9:会打印出 "99 Bottles of Beer" 这首歌的歌词。
  • +:会给一个内部的累加器加一。

语言规则还说了,除了这四个字符,其他的字符都会被直接忽略掉。

我们的任务就是,给你一段用 HQ9+ 写的程序代码(一个字符串),判断它执行后会不会产生任何输出。如果会,就输出 "YES",如果不会,就输出 "NO"。

举个栗子: 如果输入的程序是 Hi!,因为里面包含了指令 H,它会打印 "Hello, World!",所以是有输出的。我们就要回答 YES。 如果输入的程序是 Codeforces,这里面一个 HQ9+ 的指令都木有,所以它什么都不会做,自然也就没有输出了。我们就要回答 NO

是不是很简单呀?喵~

题解方法

我们来分析一下这四个指令的行为,喵~

  • H:会打印东西,所以它会产生输出
  • Q:会打印东西,所以它也会产生输出
  • 9:会打印东西,所以它同样会产生输出
  • +:只是在内部捣鼓一个数字,并不会打印出来,所以它不会产生输出
  • 其他字符:被直接忽略,当然也不会产生输出

这么一看,问题就变得超级清晰啦!一个 HQ9+ 程序会不会有输出,完全取决于它的代码里有没有出现过 HQ9 这三个字符中的任何一个。只要出现了其中任意一个,程序就会有输出。如果一个都没出现,那程序就安安静静的,啥也不干。

所以,我们的解题思路就是:

  1. 把输入的程序代码字符串拿过来。
  2. 从头到尾检查一遍这个字符串里的每一个字符。
  3. 如果在检查的过程中,我们找到了 H,或者 Q,或者 9,那我们就可以立刻确定答案是 "YES" 啦!找到一个就够了,后面的就不用再看了,可以直接结束程序,告诉大家结果,然后去晒太阳了,喵~
  4. 如果把整个字符串都检查完了,一个 HQ9 都没找到,那说明这个程序肯定不会有输出。这时候我们就打印 "NO"。

题解

这是 C++ 的实现代码,加了本喵的一些注释,希望能帮到主人喔~

cpp
#include <iostream> // 喵~ 这是输入输出流的头文件,cin 和 cout 都在这里
#include <string>   // 要操作字符串,当然少不了这个头文件啦

// 这个问题是判断一个 HQ9+ 语言的程序是否会产生输出。
// HQ9+ 语言中:
// 'H' 会打印 "Hello, World!" (有输出)
// 'Q' 会打印源代码 (有输出)
// '9' 会打印歌词 (有输出)
// '+' 只会增加累加器的值 (没有输出)
// 其他字符会被忽略 (没有输出)
// 所以,只要程序字符串中包含 'H', 'Q', '9' 中的任意一个,就会有输出。

int main() {
    // 这两行是C++竞赛里常用的小魔法,可以让输入输出变得更快一些,喵~
    // 虽然这道题数据量很小,用不用都无所谓,但养成好习惯总没错!
    std::ios_base::sync_with_stdio(false);
    std::cin.tie(NULL);

    // 声明一个 string 变量 p,就像准备一个装毛线球的小盒子
    std::string p;
    
    // 把主人输入的程序代码读到 p 这个小盒子里
    std::cin >> p;

    // 像小猫巡逻一样,一个一个地检查字符串 p 里的所有字符
    // for (char c : p) 是一个很方便的写法,可以依次取出 p 里的每个字符 c
    for (char c : p) {
        // 检查当前这个字符是不是我们关注的三个指令之一
        if (c == 'H' || c == 'Q' || c == '9') {
            // 呀!找到了一个会产生输出的指令!
            // 既然已经知道答案了,就没必要再往下找啦
            std::cout << "YES\n"; // 赶紧打印 "YES"
            return 0;             // 然后立刻结束程序,回去睡觉喵~
        }
    }

    // 如果整个循环都跑完了,说明巡逻结束,啥也没发现
    // 这就意味着程序里没有任何会产生输出的指令
    std::cout << "NO\n"; // 那就只好打印 "NO" 咯

    return 0; // 程序正常结束
}

知识点介绍

这道题虽然简单,但里面也藏着一些很有用的小知识点呢,喵~

  1. 字符串遍历 (String Traversal) 代码中用到的 for (char c : p) 是 C++11 引入的基于范围的 for 循环 (range-based for loop)。它能非常方便地遍历一个序列(比如字符串、数组、vector 等)中的每一个元素,写起来比传统的 for (int i = 0; i < p.length(); ++i) 要简洁很多,也更不容易出错。推荐主人多多使用哦!

  2. 逻辑或 || (Logical OR)if (c == 'H' || c == 'Q' || c == '9') 这个条件判断里,|| 是逻辑或运算符。它的意思是,只要两边的条件中有一个为真(true),整个表达式就为真。它还有一个“短路”特性:如果第一个条件 c == 'H' 已经是真的了,它就不会再去检查后面的 c == 'Q'c == '9' 了,因为结果已经确定。这能稍微提高一点点效率,就像猫猫看到第一条小鱼干就满足地跑开了一样,喵~

  3. 提前返回 (Early Return)if 语句块中,一旦找到符合条件的字符,我们就立刻 return 0; 来结束整个 main 函数。这是一种非常高效的编程技巧。当问题的答案已经确定时,就没必要再让程序执行多余的计算了。这在处理更复杂的问题和更大的数据时尤其重要!

  4. 快速 I/Ostd::ios_base::sync_with_stdio(false);std::cin.tie(NULL); 是在 C++ 竞赛中常见的两行代码。

    • std::ios_base::sync_with_stdio(false); 会解除 C++ 的 iostream 和 C 语言的 stdio 之间的同步,让 cincout 不用再等待 scanfprintf,从而提速。
    • std::cin.tie(NULL); 会解除 cincout 的绑定。默认情况下,每次我们用 cin 读取输入前,程序都会先刷新 cout 的缓冲区(把要打印的东西都打印出来)。解除绑定后就不需要这个等待过程了。 对于这道题来说,它们是大材小用啦,但对于需要大量输入输出的题目,这两行代码可是能救命的喵!

好啦,今天的小课堂就到这里啦!希望主人有所收获,喵~ 如果还有其他问题,随时可以再来找我玩哦!

Released under the MIT License.