分析
就是一个区间内的数,有一定要求,去掉包含4和连续的62的数这个区间的数有多少个,按照正常方法应该是标准数位dp,另附一个投机取巧算法
数位dp方法
可看做数位dp模板
//数位dp
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl "\n"
const int maxn = 1e6 + 5;
int a[20];//存下区间端点的每一位
int dp[10][2] ;
int dfs(int pos, int pre, int sta, bool limit ) {
//当前位置,前一位是什么数,前一位是不是6,是否需要判断数位上界
if(pos == 0) return 1;//个位都已经确定好了,终止条件
//保证唯一dp,这里对limit的要求可以大量剪枝,limit=1的情况很少
if(!limit && dp[pos][sta] != -1)
return dp[pos][sta];
int up = limit ? a[pos] : 9;
int tmp = 0;
for(int i = 0; i <= up; i++) {
if(pre == 6 && i == 2) continue;//出现了62
if(i == 4) continue;//出现了4,跳过
tmp += dfs(pos-1, i, i == 6, limit && i == a[pos]) ;
}
//计算结束,记录状态 ,对每个状态,只会计算一次
if(!limit) dp[pos][sta] = tmp;
return tmp;
}
int solve(int x) {
int i = 0;
while(x) {
a[++i] = x % 10;
x /= 10;
}
return dfs(i, -1, 0, true);
}
int main() {
int n,m;
memset(dp,-1,sizeof(dp));
while(scanf("%d %d",&n,&m) != EOF && (n || m)) {
printf("%d\n",solve(m) - solve(n-1));
}
return 0;
}
当做字符串处理
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int arr[1000001];
void f(){
int i;
for(i=1;i<=1000000;i++)
{
char str[10];
itoa(i,str,10);
if(strstr(str,"4")==NULL&&strstr(str,"62")==NULL)
arr[i]=1;
else
arr[i]=0;
}
}
int main()
{
int i;
f();
int n,m;
while(~scanf("%d%d",&n,&m)&&(n||m))
{
int s=0;
for(i=n;i<=m;i++)
s+=arr[i];
printf("%d\n",s);
}
}