题目描述:

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. 数学黑洞:卡普雷卡尔常数的php算法实现

    首先看一篇文章: 英国广播公司报道,6174乍看没什么奇特之处,但是,自从1949年以来,它一直令数学家.数字控抓狂.痴迷. 不管你挑的四位数是什么,早早晚晚你都会遇到6174:而且,遇到6174就只 ...

  2. 【maven学习】构建maven web项目

    Maven Web应用 创建Web应用程序 要创建一个简单的java web应用程序,我们将使用Maven的原型 - web应用插件.因此,让我们打开命令控制台,进入到C: MVN目录并执行以下命令m ...

  3. Java设计模式--观察者模式到监听器

    观察者模式是对象的行为模式.又叫做发布-订阅模式.模型-视图模式.源-监听器模式. 抽象主题角色:主题角色将所有对观察者对象的引用到保存在一个集合里,每个主题都可以拥有任意数量的观察者.抽象主题提供一 ...

  4. springcloud使用之断路器hystrix

    上一篇文章提到我们最近开了个新项目,目的是将新的业务放到新项目中,老项目单独维护,再逐步迁移老项目到新项目里.但就在前端时间生产环境发生了一个事故,事故开始的异常是我们的业务发现前端h5页面办理很慢, ...

  5. IDEA中MavenWeb项目没有新建servlet文件

    解决方案: https://blog.csdn.net/Delicious_Life/article/details/89515363

  6. C++ 每日一题 参数分析 (vector)

    首先给出原题地址: https://www.nowcoder.com/practice/668603dc307e4ef4bb07bcd0615ea677?tpId 以下是代码解析: #include& ...

  7. collections模块之defaultdict()与namedtuple()方法简单介绍

    一.defaultdict() 作用:根据数据创建字典时,需要为一些数据生成字典,而且对值得类型进行限定的时候,考虑defaultdict from collections import defaul ...

  8. 配置安全web服务

    为站点 http://system1.group8.example.com 配置TLS加密: 1.一个已签名证书从 http://server.group8.example.com/pub/tls/c ...

  9. vue设置全局变量和修改

    1. 只读的全局变量 对于只读的全局变量,知道的有以下两种使用方式: 1)global.js 模块中定义:其他模块import后再使用即可 1.1)定义 import Vue from 'vue'; ...

  10. spring Boot 学习(二、Spring Boot与缓存)

    一.概述1. 大多应用中,可通过消息服务中间件来提升系统异步通信.扩展解耦能力 2. 消息服务中两个重要概念: 消息代理(message broker)和目的地(destination) 当消息发送者 ...