题解:CF204A Little Elephant and Interval
CF204A Little Elephant and Interval
题意
给定 \(l,r\) 求区间 \([l,r]\) 中数字首位和尾位相等的数字的个数。
数据范围:$1 \leq l \leq r \leq 10^{18} $(开 long long)
思路
- 首先想到通过暴力枚举区间内所有数,每次检测是否符合要求,但显然对于大范围的区间会超时。
- 那么我们考虑找规律,直接对区间内的合法数统计比较麻烦,那我们不妨统计 \([1,r]\) 和 \([1,l-1]\) 两个区间内合法数的个数,并做差。当右端点小于 \(10\) 时,那么个数一定为右端点的值。当右端点不小于 \(10\) 时,我们举几个例子:
i [1,i]总数 [10,i]总数
12 -> 10 -> 10-9=1
21 -> 10 -> 10-9=1
25 -> 11 -> 11-9=2
33 -> 12 -> 12-9=3
36 -> 12 -> 12-9=3
我们发现对于一个数 \(i\),在 \([10,i]\) 中,当 \(i\) 首位比尾位大,那么结果为 \(\lfloor \frac{i}{10} \rfloor - 1\),否则为 \(\lfloor \frac{i}{10} \rfloor\)。原因是个位每 \(10\) 一个循环,每个循环内一定有合法数,如 \(11,22,\dots,101,111,\dots,202,212\dots\),当尾位比首位小时,在该循环无法构成首尾相等,如 \(31 < 33\)。
这是思路,更多详情请看代码。
代码
#include<bits/stdc++.h>
using namespace std;
long long get_first(long long n){ //取首位
while(n>=10) n/=10;
return n;
}
long long solve(long long n){
if(n<10) return n;
long long ans=n/10+9, last=n%10, first=get_first(n); //last为尾位,first为首位,答案别忘了+9
if(first>last) ans--; //比较首尾,首比尾大-1
return ans;
}
int main(){
long long l, r;
cin >> l >> r;
cout << solve(r)-solve(l-1) << endl;
return 0;
}
完结撒花!

浙公网安备 33010602011771号