1 条题解
-
0
一、思路分析(超详细)
1. 题目核心:镜像数对的定义拆解
镜像数对要求:对于正整数对 ,需同时满足两个条件:
- 的最后一位数字 = 的第一位数字;
- 的第一位数字 = 的最后一位数字。
我们的目标是统计 时,满足上述条件的数对总数。
2. 暴力解法的致命问题
若直接遍历所有 和 (范围 ),逐一验证条件:
- 时间复杂度为 ;
- 当 时,,远超计算机运算能力(1秒约能处理 次操作),必然超时。
因此必须通过“特征统计”优化,将时间复杂度降至 。
3. 优化核心:数字的“首位-末位”特征
每个正整数 可抽象为一个特征对 :
- (first): 的首位数字(正整数首位非0);
- (last): 的末位数字(可为0)。
镜像数对的条件可转化为: 若 的特征是 , 的特征是 ,则需满足: 且 → 即 的特征是 。
例如:
- 的特征是 ,则所有特征为 的 (如21、121、201等)都能和 组成镜像数对;
- 若特征为 的数字有 个,特征为 的数字有 个,则这两类数字能组成的镜像数对数量为 。
4. 解题步骤(O(N) 时间复杂度)
步骤 操作说明 1 统计特征:遍历 的所有数字,计算每个数字的首位 和末位 ,用二维数组 记录该特征对的数字数量 2 计算总数:遍历所有可能的特征对 (),累加 ,得到总镜像数对数量 3 防溢出:总数量可能极大(如 时结果超 ),需用 long long存储结果5. 关键细节
- 首位计算:通过循环除以10,直到数字小于10(如123 → 12 → 1);
- 末位计算:直接对10取余(如123 % 10 = 3);
- 特征对的范围:(正整数首位非0),,但数组可开 覆盖所有可能。
二、带详细注释的C++代码
#include <bits/stdc++.h> using namespace std; // 函数功能:计算正整数x的首位数字 // 输入:正整数x // 输出:x的首位数字(如x=123,返回1;x=5,返回5) int get_swsz(int x) { // 循环除以10,直到x小于10(只剩最后一位,即首位) while (x >= 10) { x /= 10; } return x; } int main() { int n; // 读取输入的N(所有数字的上限) scanf("%d", &n); // 二维计数数组:cnt[f][l] 表示“首位为f、末位为l”的数字数量 // f和l的范围是0~9(f≠0因为正整数首位非0),数组初始化为0 int cnt[10][10] = {0}; // 遍历1~N的所有数字,统计每个数字的特征对(f,l) for (int x = 1; x <= n; x++) { // 步骤1:计算x的末位数字(对10取余) int last = x % 10; // 步骤2:计算x的首位数字(调用自定义函数) int first = get_swsz(x); // 步骤3:更新特征对计数:首位first、末位last的数字数量+1 cnt[first][last]++; } // 总镜像数对数量(必须用long long,避免溢出:N=2e5时总数可达(2e5)^2=4e10) long long total = 0; // 遍历所有可能的首位f(0~9)和末位l(0~9) for (int f = 0; f < 10; ++f) { for (int l = 0; l < 10; ++l) { // 特征对(f,l)的数字有cnt[f][l]个,特征对(l,f)的数字有cnt[l][f]个 // 这两类数字能组成的镜像数对数量 = cnt[f][l] * cnt[l][f] // 累加所有组合的数量,得到总对数 total += (long long)cnt[f][l] * cnt[l][f]; } } // 输出最终结果 cout << total << endl; return 0; }三、代码关键细节补充
1. 首位计算函数
get_swsz- 逻辑:对于数字 ,只要大于等于10,就不断除以10,直到只剩一位(即首位);
- 示例: → 25/10=2(<10)→ 返回2; → 1234→123→12→1 → 返回1。
2. 计数数组
cnt[10][10]- 初始化:用
{0}初始化,确保所有元素初始值为0; - 索引含义:
cnt[f][l]中,第一个维度是首位 ,第二个维度是末位 ; - 示例:数字11的特征是(1,1),则
cnt[1][1] +=1;数字12的特征是(1,2),则cnt[1][2] +=1。
3. 溢出防护
- 为什么用
long long?
假设 ,若所有数字的特征都是(1,1),则cnt[1][1]=2e5,cnt[1][1] * cnt[1][1] = 4e10,超过int的最大值(约2e9),必须用long long(最大值约9e18); - 强制类型转换:
(long long)cnt[f][l] * cnt[l][f]先将cnt[f][l]转为long long,再相乘,避免中间结果溢出。
4. 样例验证(以样例1 N=25为例)
- 统计特征对:
- (1,1):数字1、11 → cnt[1][1]=2;
- (1,2):数字12 → cnt[1][2]=1;
- (2,1):数字21 → cnt[2][1]=1;
- (2,2):数字2、22 → cnt[2][2]=2;
- (3,3)~(9,9):各1个 → cnt[3][3]~cnt[9][9]各=1;
- 计算总数:
- cnt[1][1]cnt[1][1] = 22=4;
- cnt[1][2]cnt[2][1] =11=1;
- cnt[2][1]cnt[1][2] =11=1;
- cnt[2][2]cnt[2][2] =22=4;
- cnt[3][3]*cnt[3][3]~cnt[9][9]cnt[9][9]:7个11=7;
- 总和:4+1+1+4+7=17,与样例输出一致。
四、时间/空间复杂度分析
- 时间复杂度:
遍历1~N的时间是 ,遍历10×10特征对的时间是常数级(100次),总复杂度由 主导; - 空间复杂度:
仅使用固定大小的二维数组(10×10=100个int),无额外动态空间,属于常数空间。
该解法完全满足题目 的数据规模要求,运行效率极高。
- 1
信息
- ID
- 5477
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 7
- 标签
- (无)
- 递交数
- 42
- 已通过
- 12
- 上传者