题解:洛谷 P1200 你的飞碟在这儿

【题目来源】

洛谷:P1200 [USACO1.1] 你的飞碟在这儿 Your Ride Is Here - 洛谷

【题目描述】

众所周知,在每一个彗星后都有一只 UFO。这些 UFO 时常来收集地球上的忠诚支持者。不幸的是,他们的飞碟每次出行都只能带上一组支持者。因此,他们要用一种聪明的方案让这些小组提前知道谁会被彗星带走。他们为每个彗星起了一个名字,通过这些名字来决定这个小组是不是被带走的那个特定的小组(你认为是谁给这些彗星取的名字呢?)。关于如何搭配的细节会在下面告诉你;你的任务是写一个程序,通过小组名和彗星名来决定这个小组是否能被那颗彗星后面的 UFO 带走。

小组名和彗星名都以下列方式转换成一个数字:最终的数字就是名字中所有字母的积,其中 \(A\)\(1\)\(Z\)\(26\)。例如,USACO 小组就是 \(21\times 19\times 1\times 3\times 15 = 17955\)。如果小组的数字 \( mod \ 47\) 等于彗星的数字  \(mod \ 47\),你就得告诉这个小组需要准备好被带走!(记住“\(a\ mod\ b\)”是 \(a\) 除以 \(b\) 的余数,例如 \(34 \ mod \ 10\) 等于 \(4\)

写出一个程序,读入彗星名和小组名并算出用上面的方案能否将两个名字搭配起来,如果能搭配,就输出 GO,否则输出 STAY。小组名和彗星名均是没有空格或标点的一串大写字母(不超过 6 个字母)。

【输入】

\(1\) 行:一个长度为 \(11\)\(66\) 的大写字母串,表示彗星的名字。

\(2\) 行:一个长度为 \(11\)\(66\) 的大写字母串,表示队伍的名字。

【输出】

【输入样例】

COMETQ
HVNGAT

【输出样例】

GO

【核心思想】

  1. 问题分析:给定彗星名和小组名两个字符串,将每个字符串中所有字母转换为对应数字(\(A=1, B=2, \ldots, Z=26\))后连乘得到两个数值,若两数对 \(47\) 取模结果相等则输出 GO,否则输出 STAY

  2. 算法选择

    • 字符串遍历 + 字符映射:逐字符读取字符串,利用 ASCII 码偏移将大写字母映射为 \(1 \sim 26\)
    • 模运算:连乘过程中或最后对 \(47\) 取模,避免整数溢出
  3. 关键步骤

    • 初始化m1 = 1, m2 = 1,作为连乘的初始值
    • 处理彗星名 \(s1\)
      • 遍历每个字符 s1[i],计算 t = s1[i] - 'A' + 1 得到字母对应数字
      • m1 *= t 累乘所有字母值
    • 处理小组名 \(s2\):同上,结果存入 m2
    • 取模比较m1 % 47 == m2 % 47 则输出 GO,否则输出 STAY
  4. 时间/空间复杂度

    • 时间复杂度:\(O(|s1| + |s2|)\),线性遍历两个字符串
    • 空间复杂度:\(O(1)\),仅需两个整型变量存储乘积
  5. 字符串映射的核心思想

    • ASCII 码偏移映射:利用 'A' 的 ASCII 值为 \(65\),通过 ch - 'A' + 1\(A \sim Z\) 映射为 \(1 \sim 26\)
    • 连乘哈希:将字符串压缩为一个数值特征,通过模 \(47\) 进一步压缩为同余类
    • 模运算防溢出:虽然题目保证字符串长度 \(\leq 6\) 且乘积不会溢出 int,但取模操作是哈希类问题的标准做法
    • 同余判定:两数模 \(47\) 相等即认为"匹配",这是一种简单的哈希碰撞容忍策略
    • 适用于字符串特征提取、简单哈希匹配类问题

【解题思路】

【算法标签】

入门 #字符串入门

【代码详解】

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

int main()
{
    string s1, s2;  // 定义2个字符串
    int m1 = 1, m2 = 1;  // 因为连乘,所以初始值为1
    cin >> s1 >> s2;  // 输入s1和s2
    for (int i=0; i<s1.length(); i++) {  // 遍历s1
        int t = s1[i] - 'A' + 1;  // 获得每个字符对应的1-26的数字
        m1 *= t;  // 进行连乘
    }
    for (int i=0; i<s2.length(); i++) {  // 遍历s2
        int t = s2[i] - 'A' + 1;  // 获得每个字符对应的1-26的数字
        m2 *= t;  // 进行连乘
    }
    m1 = m1 % 47;  // 分别对两个结果进行取余运算
    m2 = m2 % 47;
    if (m1 == m2) {  // 如果相同则输出GO
        cout << "GO";
    } else {  // 否则输出STAY
        cout << "STAY";
    }
    return 0;
}

【运行结果】

COMETQ
HVNGAT
GO
posted @ 2026-08-03 08:46  团爸讲算法  阅读(22)  评论(0)    收藏  举报