3257. 七减一
Time limit per test: 2.0 seconds
Memory limit: 256 megabytes
仲马是一个很七减一的人,他经常会说七减一七减一七减一,你们也许觉得他说的是 666,但实际上七减一是比 6 更为高贵的存在。仲马所有的表情包和打出来的数字中都要把 6 换成七减一。校赛临近了,仲马的七减一之魂开始燃烧了,他竟然想要打出 l 到 r 之间所有的数字并且将里面所有的 6 替换成七减一,然而当他完成这一切时他早已忘记了他打出了多少个高贵的七减一,为此他十分痛苦,你能告诉他他究竟将多少个 6 替换为了七减一么?
Input
不超过 100 组输入,处理到文件结束。
每组数据一行,有两个数字 l,r,用空格分开。
对于 40% 的数据,满足:1≤l≤r≤104。
对于 100% 的数据,满足:1≤l≤r≤1018。
Output
每组数据输出一行结果。
Examples
input
1 6 1 666
output
1 201
题解:数位dp
dp[i][j]表示i位数最高位为j的所有数中6的个数总和。
先用init预处理出所有dp[i][j]
再找出所有小于x的数中6的个数,具体方法也是和杭电那道不要62相似
要注意的是当高位为6时需要加上剩下所有数的个数(因为开头那个数是6)
具体实现见代码。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <set>
#include <map>
#include <vector>
#define vi vector<int>
#define ll long long
#define P pair<int,int>
using namespace std;
const int maxn = 1e6 + 10;
bool lucky[maxn];
ll f[20][20];//f[i][j]表示i位数中最高位为j的所有数中所满足条件的数的个数
ll ten(int t)
{
ll tmp = 1;
for(int i = 0; i < t; i++)
tmp *= 10;
return tmp;
}
void init_dp()
{
for(int i = 0; i <= 9; i++)
if(i == 6) f[1][i] = 1;
for(int i = 2; i <= 19; i++)//数的位数
for(int j = 0; j <= 9; j++)
{
for(int k = 0; k <= 9; k++)
f[i][j] += f[i - 1][k];
if(j == 6) f[i][j] += ten(i - 1);
}
}
ll count(ll t)
{
int digit[20]={0};//记录每一位的数
int num = 1;
while(t)
{
digit[num++] = t % 10;
t /= 10;
}
ll ans = 0;
for(int i = num - 1; i >= 1; i--)
{
for(int j = 0; j < digit[i]; j++)
{
ans += f[i][j];
}
if(digit[i] == 6){
ll temp = 0;
for(int j = i - 1; j >= 1; j--)
temp = temp * 10 + digit[j];
ans += temp;
}
}
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
init_dp();
ll n, m;
while(cin >> n >> m)
{
cout << 1LL * (count(m + 1) - count(n)) << endl;
}
return 0;
}