1 100 0 0
80
题解:这道题反过来求含有4,62的个数。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define ll long long
using namespace std;
int l,r;
int dp[10][3];///0:合法 1:2开头 2:不合法
///dp[i][j] 表示长度为i的数 的 j状态
/*
此题是把一个数分为多个区间求解的
如:n=930818 就有[1,900000),[900000,930000),[930000,930800),
[930800,930810),[930810,930818];
*/
///预处理
void init() {
dp[0][0]=1;
for(int i=1; i<=8; i++) {
dp[i][0]=dp[i-1][0]*9-dp[i-1][1];
dp[i][1]=dp[i-1][0];
dp[i][2]=dp[i-1][2]*10+dp[i-1][1]+dp[i-1][0];
}
}
int solve(int n) {
int nn=n;
int num[10];
int len=1;
while(n) {
num[len++]=n%10;
n/=10;
}
num[len]=0;
int ans=0;
int flag=0;
for(int i=len-1; i>=1; i--) {
ans+=dp[i-1][2]*num[i];
if(flag) ans+=dp[i-1][0]*num[i];///如果出现了62或4
if(!flag&&num[i]>4) ans+=dp[i-1][0]; ///可以放4
if(!flag&&num[i]>6) ans+=dp[i-1][1]; ///62
if(!flag&&num[i+1]==6&&num[i]>2) ans+=dp[i][1]; ///还是62
if((num[i+1]==6&&num[i]==2)||num[i]==4) ///如:你要算的区间是[62000,62300),
///62****怎么放都行
flag=1;
}
return nn-ans;
}
int main() {
init();
while(cin>>l>>r&&(l||r)) {
printf("%d\n",solve(r+1)-solve(l));
}
return 0;
}
原文地址:http://blog.csdn.net/acm_baihuzi/article/details/45223281