题目描述:

Little Elephant and Interval

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

The Little Elephant very much loves sums on intervals.

This time he has a pair of integers l and r (l ≤ r). The Little Elephant has to find the number of such integers x (l ≤ x ≤ r), that the first digit of integer x equals the last one (in decimal notation). For example, such numbers as 101, 477474 or 9 will be included in the answer and 47, 253 or 1020 will not.

Help him and count the number of described numbers x for a given pair l and r.

Input

The single line contains a pair of integers l and r (1 ≤ l ≤ r ≤ 1018) — the boundaries of the interval.

Please, do not use the %lld specifier to read or write 64-bit integers in С++. It is preferred to use cin, cout streams or the %I64d specifier.

Output

On a single line print a single integer — the answer to the problem.

Examples

Input

Copy

2 47

Output

Copy

12

Input

Copy

47 1024

Output

Copy

98

Note

In the first sample the answer includes integers 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44.

思路:

题目是说给一个区间,求这个闭区间内有多少个第一位等于最后一位的数。刚开始,由于数可能会比较大,想到了字符串表示,有找到了一些规律如下:

1---------9---------1*9

11--------99--------1*9

101---------999------10*9

1001-----------9999------100*9

....

这样就先确定区间端点所在的位置,位置中间的整段可以直接求出来。关键在于判断,怎么判断区间端点在整段里前面有多少个数,后面有多少个数。先看只有一个数字的数,然后两个及以上数字的数,先看第一位的元素个数res,再看剩下的位数组成数字的大小tmp和最后一位s[len-1]的大小,如果小于这一部分tmp就为0,大于等于就加上tmp-s[0],再看s[0]与s[len-1]的大小,如果s[0]>s[len-1]就说明包含不了这个最后的数(比如2021,1<2,所以包含不了2022),tmp--,否则tmp就不用减,返回res+tmp。由于这种方法思路复杂,需要很多特判,考虑容易不全,一旦思路转到这个上面,写不对就完了。

字符模拟代码:

#include <iostream>
#include <string>
using namespace std;
string l,r;
long long len1;
long long len2;
long long ans = 0;
long long q_mod(long long a,int b)
{
long long res = 1;
if(b==-1)
{
return 1;
}
while(b)
{
if(b&1) res = res*a;
a = a*a;
b>>=1;
}
return res;
}
long long sub(string s)
{
//cout << "s " << s << endl;
int len = s.size();
if(len==1)
{
return s[0]-'0';
}
long long res = 0;
res = (s[0]-'1')*q_mod(10,len-2);
long long tmp = 0;
for(int i = 1;i<len;i++)
{
tmp = 10*tmp+s[i]-'0';
}
//cout << "tmp " << tmp << endl;
if(tmp>=s[0]-'0')
{
tmp-=(s[len-1]-'0');
tmp /= 10;
if(s[len-1]>=s[0])
{
tmp+=1;
}
}
else
{
tmp = 0;
}
return res+tmp;
}
int main()
{
cin >> l >> r;
len1 = l.size();
len2 = r.size();
for(int i = len1+1;i<len2;i++)
{
ans += 9*q_mod(10,i-2);
}
long long tmp1 = sub(l);
if(l[0]==l[len1-1]) tmp1--;
long long tmp2 = sub(r);
//cout << "tmp1 " << tmp1 << " tmp2 " << tmp2 << endl;
//cout << "q_mod " << 9*q_mod(10,len1-2) << endl;
if(len1==len2)
{
ans += tmp2-tmp1;
}
else
{
ans += (9*q_mod(10,len1-2)-tmp1)+tmp2;
}
cout << ans << endl;
return 0;
}

当然这题可以有跟简单的考虑。我们要求[l,r]的满足条件的数,不如求[1,l-1],[1,r]的数,最后两个区间相减。同时也不用字符串,直接找规律,直接将数除以10,就得到它在[11,n]中满足条件的数。比如1024除以10就是102,表示[11,1024]里有102个满足条件的数。再加上9就得到[1,1024]的数。

至于为什么会这样,我们依据上面的规律

1---------9---------1*9

11--------99--------1*9

101---------999------10*9

1001-----------9999------100*9

....

发现[11,n]中满足条件的数是\(num = 10^{len(n)-1}-1\),如果n=99...9的话,其中len(n)是n的长度。我们可以发现99999/10=9999,实际上就是\(num=10^4-1\)。其实一个数满足首末元素相等的话,我们除以十就忽略掉了末元素。实际上除以十就是上一种思路的简化表示。上一种思路中的res与tmp部分做的就是这个事。举个栗子:1024,1024/10=102,这102是怎么来的呢:999/10+2-0+1,999/10表示前面整段满足条件的个数,2-0+1做的就是上一种思路做的。

所以这一点后,实现就简单了,思路也简单了。注意的是一位数的特判,直接返回即可。

找规律代码:

#include <iostream>
using namespace std;
long long l,r;
long long cal(long long n)
{
long long ans = n/10;
if(n<10) return n;
ans += 9;
int tmp = n%10;
while(n>=10)
{
n /= 10;
}
if(n>tmp)
{
ans--;
}
return ans;
}
int main()
{
cin >> l;
cin >> r;
cout << cal(r)-cal(l-1) << endl;
return 0;
}

然后,这道题是跟数的组成有关的,因此可以考虑数位dp,求出[1,l-1]与[1,r]的满足条件的数,相减即可,思路与上一种类似。

dp[pos] [num]表示处理到第pos位,第一位是num的满足条件的数的个数。代码中st表示前一位数,lead表示有无前导零,limit表示对当前位有无限制。注意数据范围。

数位dp代码:

#include <iostream>
#include <memory.h>
using namespace std;
long long dp[20][10];
int x[20];
int cnt;
long long dfs(int pos,int num,int st,int limit,int lead)
{
if(pos<1) return num==st;
if(dp[pos][num]!=-1&&!limit&&!lead) return dp[pos][num];//记忆化搜索
int up = limit?x[pos]:9;
long long res = 0;
for(int i = 0;i<=up;i++)
{
if(lead&&(i==0))//若有前导零,这一位也是零,继续处理下一位
{
res += dfs(pos-1,0,st,i==up&&limit,lead);
}
if(lead&&i)//若有前导零,这一位不是零,以这一位为数的第一位
{
if(1==pos) st = i;//如果这是数的唯一一位,也是最后一位,把st设为i
res += dfs(pos-1,i,st,limit&&i==up,!lead);
}
if(!lead)//若无前导零,正常递归
{
res += dfs(pos-1,num,i,limit&&i==up,lead);
}
}
if(!limit&&!lead) dp[pos][num] = res;//记录
return res;
}
long long Count(long long n)
{
cnt = 0;
while(n)
{
x[++cnt] = n%10;
n/=10;
}
/*for(int i = 1;i<=cnt;i++)
{
cout << x[i] << " ";
}
cout << endl;*/
return dfs(cnt,0,-1,1,1);
}
int main()
{
long long l,r;
cin >> l >> r;
memset(dp,-1,sizeof(dp));
//cout << "rr " << Count(r) << endl;
//cout << "ll " << Count(l-1) << endl;
cout << Count(r)-Count(l-1) << endl;
}

参考文章:

luminous11,CodeForces 204A Little Elephant and Interval,https://blog.csdn.net/luminous11/article/details/43971413

My_ACM_Dream,codeforces 204A Little Elephant and Interval (数位dp),https://blog.csdn.net/my_acm_dream/article/details/43373419

Mathison,数字组成的奥妙——数位dp,https://www.luogu.org/blog/virus2017/shuweidp

wust_wenhao,数位dp总结 之 从入门到模板,https://blog.csdn.net/wust_zzwh/article/details/52100392

Codeforces D. Little Elephant and Interval(思维找规律数位dp)的更多相关文章

  1. 找规律/数位DP HDOJ 4722 Good Numbers

    题目传送门 /* 找规律/数位DP:我做的时候差一点做出来了,只是不知道最后的 is_one () http://www.cnblogs.com/crazyapple/p/3315436.html 数 ...

  2. 2017年icpc西安网络赛 Maximum Flow (找规律+数位dp)

    题目 https://nanti.jisuanke.com/t/17118 题意 有n个点0,1,2...n-1,对于一个点对(i,j)满足i<j,那么连一条边,边权为i xor j,求0到n- ...

  3. CF809C(找规律+数位DP)

    老年选手需要多写一些思维题qwq. 通过打表很容易发现对于(i,j),值为(i-1)^(j-1)+1,然后本题就没了qwq. 矩阵差分还是很容易想到的,容斥成四个矩阵. 然后看到异或很容易想到三件事: ...

  4. Tetrahedron(Codeforces Round #113 (Div. 2) + 打表找规律 + dp计数)

    题目链接: https://codeforces.com/contest/166/problem/E 题目: 题意: 给你一个三菱锥,初始时你在D点,然后你每次可以往相邻的顶点移动,问你第n步回到D点 ...

  5. Codeforces 193E - Fibonacci Number(打表找规律+乱搞)

    Codeforces 题目传送门 & 洛谷题目传送门 蠢蠢的我竟然第一眼想套通项公式?然鹅显然 \(5\) 在 \(\bmod 10^{13}\) 意义下并没有二次剩余--我真是活回去了... ...

  6. Codeforces 288E - Polo the Penguin and Lucky Numbers(数位 dp+推式子)

    题目传送门 似乎我的解法和官方题解不太一样 纪念自己独立做出来的一道难度 2800 的题. 我们记 \(ans(x)\) 为 \([444...44,x]\) 的答案,显然答案为 \(ans(r)-a ...

  7. Codeforces 582D - Number of Binominal Coefficients(Kummer 定理+数位 dp)

    Codeforces 题目传送门 & 洛谷题目传送门 一道数论与数位 dp 结合的神题 %%% 首先在做这道题之前你需要知道一个定理:对于质数 \(p\) 及 \(n,k\),最大的满足 \( ...

  8. Codeforces 204A Little Elephant and Interval

    http://codeforces.com/problemset/problem/204/A 题意:给定一个[L,R]区间,求这个区间里面首位和末尾相同的数字有多少个 思路:考虑这个问题满足区间加减, ...

  9. [CodeForces - 848B] Rooter's Song 思维 找规律

    大致题意: 有一个W*H的长方形,有n个人,分别站在X轴或Y轴,并沿直线向对面走,第i个人在ti的时刻出发,如果第i个人与第j个人相撞了 那么则交换两个人的运动方向,直到走到长方形边界停止,问最后每个 ...

随机推荐

  1. Vmvare v12下搭建Ubuntu操作系统-18.04-desktop-amd64.iso镜像环境

    1.选择[典型],点击下一步.  2.找到ubuntu镜像文件所在位置,如图所示:  3.配置用户信息  4.设置安装位置  5.磁盘尽量大一些,笔者设置40g  6.自定义修改硬件信息  7.内存建 ...

  2. php 回调函数结合闭包(匿名函数)的使用示例

    <?php /** * php 回调函数结合闭包(匿名函数)的使用 */ function callback( $callback ){ $variable = 'program'; $ret1 ...

  3. scala 抽象类

    package com.jason.qianfeng abstract class Person(val gender: String) { val name: String val age: Int ...

  4. layui switch 确定之后才变更状态

    let x = data.elem.checked; data.elem.checked = !x; form.render(); 完整代码 form.on('switch(is_enable)', ...

  5. 【转帖】为什么有了Compose和Swarm,还会有Kubernetes的出现?

    为什么有了Compose和Swarm,还会有Kubernetes的出现? https://www.cnblogs.com/chenqionghe/p/11474486.html 图非常好 一.k8s设 ...

  6. [转帖]记一次KUBERNETES/DOCKER网络排障

    记一次KUBERNETES/DOCKER网络排障 https://coolshell.cn/articles/18654.html 记得之前在一个公众号里面看过这个文章 讲的挺好的.. 物理机直接跑d ...

  7. [转帖]OLTP、OLAP与HTAP

    OLTP.OLAP与HTAP https://blog.csdn.net/ZG_24/article/details/87854982   OLTP On-Line Transaction Proce ...

  8. RWMutex:共享/专有的递归互斥锁

    具有共享/独占访问权限,且具有升级/降级功能的互斥锁 介绍 我的目标是创建可以充当读/写锁定机制的对象.任何线程都可以锁定它以进行读取,但是只有一个线程可以锁定它以进行写入.在写入线程释放它之前,所有 ...

  9. libevent源码分析三--signal事件响应

    libevent支持io事件,timeout事件,signal事件,这篇文件将分析libevent是如何组织signal事件,以及如何实现signal事件响应的. 1.  sigmap 类似于io事件 ...

  10. (八)pdf的构成之文件体(page属性)

    资源(Resources) 类型:字典 属性: Font :一个字典,内部是该资源包含的各个字体的名称(字体名称F开头) ProcSet :该资源中使用图画还是文字,可选 /PDF /Text /Im ...