ACWING\1912. 里程表

文章描述了一种处理计算100到10^16范围内有趣数字出现次数的算法。通过反向枚举全相同数并改变一位来构造有趣数字,避免了暴力枚举导致的时间超限问题。代码示例展示了如何遍历和检查这些数字是否在给定范围内。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

输入格式

共一行,包含两个整数 X 和 Y。

输出格式

输出奶牛们在旅途中发出叫声的次数。

数据范围
100≤X≤Y≤10^16
输入样例:
110 133
输出样例:
13
样例解释

110∼133 之间的所有数字中,有趣数字为:110,112,113,114,115,116,117,118,119,121,122,131,133。

枚举

注意!!! 数据范围是最大16位数,必须long long才能hold住
思路:

  • 错误的: 暴力枚举x~y范围的,一定超时!
  • 那么反向思维,有趣的数肯定没这么多,那么枚举所有有趣数,判断是否在范围即可
  • 如何构造有趣数: 最简单的方法就是从全相同的数改变一个即可
  • 注意: 前导0的数不成立,排除即可。

具体写法见注释

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string>

using namespace std;

int main(){
    long long x,y;
    cin>>x>>y;
    int ans = 0;
    // 遍历3~16位数的“全相同数” 构造有趣数
    for(int i = 3; i <= 17; ++i)
    {
    	// jjj...j,由i个j构成的全相同数 
    	for(int j = 0; j < 10; ++j)
    	{
    		// 构造数字的字符串形式
    		string str(i, '0'+j);
    		// 将全j数中的某一位替换为k
    		for(int k = 0; k < 10; ++k)
    		{
    			if(k == j) continue; // 相同非替换
    			// 替换第u位的数
				for(int u = 0; u < i; ++u)
				{
					str[u] = '0' + k;
					long long num = atoll(str.c_str());
					// 在范围内且无前导零
					if(str[0] != '0' && x <= num && num <= y) ans++;
					// 恢复现场
					str[u] = ('0'+j);
				}
			}
		}
	}
	
	cout<<ans<<endl;
    
    
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

AlwaysDayOne

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

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

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

打赏作者

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

抵扣说明:

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

余额充值