卧薪尝胆,厚积薄发。
不要62
Date: Sun May 27 07:05:19 CST 2018 In Category: NoCategory

Description:

求 $[L,R]$ 内不含 $4$ 和 $62$ 的数。
$0<L\le R < 1000000$ 多组询问

Solution:

数位 $DP$ ,先处理出 $f[i][j]$ 表示第 $i$ 位数字为 $j$ 的方案数,对于不合法的状态转移时避免即可,即 $[j\times10^{i},(j+1)\times 10^{i})$ ,计算时用前缀和,因为区间右开,所以先将数字 $+1$ ,从高位向低位沿着边界处理,因为中间如果有不合法状态要 $break$ ,从低位开始处理时 $break$ 会少一些情况,如果边界出现了不合法的情况,直接 $break$ 掉,因为之后沿着边界走也不可避免他们。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int n,m;
int f[10][10];
int bit[10],l;
void pre()
{
memset(f,0,sizeof(f));
f[0][0] = 1;
for(int i = 1;i <= 7;++i)
{
for(int j = 0;j <= 9;++j)
{
if(j == 4)continue;
for(int k = 0;k <= 9;++k)
{
if(k == 4 || (j == 6 && k == 2))continue;
f[i][j] += f[i - 1][k];
}
}
}
return;
}
int calc(int t)
{
++t;
int ans = 0;
l = 0;
memset(bit,0,sizeof(bit));
while(t > 0)
{
++l;
bit[l] = t % 10;
t /= 10;
}
for(int i = l;i >= 1;--i)
{
for(int j = 0;j < bit[i];++j)
{
if(bit[i + 1] == 6 && j == 2)continue;
ans += f[i][j];
}
if(bit[i] == 4 || (bit[i + 1] == 6 && bit[i] == 2))break;
}
return ans;
}
int main()
{
pre();
while(scanf("%d%d",&n,&m) && n != 0 && m != 0)
{
cout << calc(m) - calc(n - 1) << endl;
}
return 0;
}
In tag: DP-数位DP
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡