现在的位置: 首页 > 综合 > 正文

ACMore-1488(数位DP)

2013年11月07日 ⁄ 综合 ⁄ 共 1538字 ⁄ 字号 评论关闭

1488: 1的数量

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 108  Solved: 26

Description

求区间[a,b]包含1的数量。例如区间[111,112], 整个区间包含两个数,分别为111,112,111包含3个1,而112包含2个1,所以区间[111,112]总共包含5个1.

Input

多组测试数据。

每组测试数据包含两个整数a, b, 1 <= a <= b <= 10^18.

Output

每组测试输出一行,表示1的数量,结果mod 10^9+7.

Sample Input

111 1121 1000

Sample Output

5301

HINT

Source

一晚上就做了这么一道题目,,坑死了,,,到最后还是A了,,,还是有点小高兴,要是最后没有A,我就急死了!!!!

看了好长时间别人的代码,

我觉得,不好写,这么水的一道,居然就写了这么长时间,如果是稍微难一点的,我估计就完蛋了,明天还得及时复习呀...诶..

贴出代码:

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <iostream>
#include <string>
/*
 *一晚上就在搞这个题目,,晕死,,
 *总算是A掉了,诶呀,,本来老早就可以A掉的.就是那个long long int 的没有注意,
 *一直没有测出来
 */ 

using namespace std;

const int M = 1000000000 + 7;

long long int a, b;

long long int d[33];

/*
 *d[i]表示第i位为最高位的时候0-99999(i - 1个9)的时候出现1的个数;
 *可以推算得. d[i] = 10 * d[i - 1] + pow(10.0, i - 1);
 */

void init()
{
	d[0] = 0;
	for (int i = 1; i <= 19; i++)
	{
		d[i] = 10 * d[i - 1] + pow(10.0, i - 1); //这是根据你模拟几个数,推算出来的 
	}
}		

long long int cal(long long int x)
{
	int cnt = 1;
	int a[33];
	if (x == 0)
	{
		return 0;
	}
	while (x)
	{
		a[cnt++] = x % 10;//将你得到的数字存起来. 
		x /= 10;
	}
	long long int ans = 0;
	long long int temp = 0;
	int flag = 0;
	for (int i = cnt - 1; i >= 1; i--)
	{
		ans += temp * pow(10, i - 1) * (a[i]);//表示记录前面已经访问了多少个1了, 
		if (a[i] > 1) 
		{
			ans += (long long int)a[i] * d[i - 1] + pow(10, i - 1);
		}
		else if (a[i] == 1)
		{
			temp++;
			ans += (long long int )a[i] * d[i - 1];
		}
	}
	ans = ans + temp;//这个是最精华的地方,因为,你每次都是从00-999...所以你的1000...的1其实是没有算上的而你下一个
					 //1100...的第二个1,你只算了1000...---1099...的数字,却没有算上那个1,所以最终得不到你想要的结果
					 //再举个简单的例子,当为1000的时候,每次都没有算,你到最后还是要算有一次的,还例如1100,第一次你算的是
					 // 0 - 999 缺一个1000的1,第二次你算的是1000 - 1099 又却了一个1100的1; 
	return ans;
}

int main()
{
	init();
	while (scanf("%lld%lld", &a, &b) != EOF)
	{
		printf("%lld\n", (cal(b) - cal(a - 1)) % M);
	}
	return 0;
}

抱歉!评论已关闭.