Solution
- 显然暴力是会出滑稽的
- f[i][j] 表示共有i位,其中最高位为j的数的个数
状态转移:
f[i,j]代表开头是j的i位数中不含”62”或”4”的数有几个。
如f[2,6]包含60,61,63,65,66,67,68,69
f[0,0]=1;
for(i=1 7)
for(j=0 9)//枚举第i位
for(k=0 9)//枚举第i−1位
ifj<>4||(j=6andk=2)continue;
f[i,j]=f[i−1,k]+f[i,j];关于统计答案:
先预处理出数字x每一位的数字是几,d[1]保存个位,d[2]保存十位,依次类推
注意f数组的含义是有i位的数字的数的个数,而不是前i位的所有情况
因此从高位开始枚举每i位中比d[i]小的数,加入答案
当第i位出现4或者与更高的位上的数字组成62的情况时,停止统计- 最后的答案是solve(m+1)-solve(n),
Code
// by spli
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
#define LL long long
using namespace std;
int n,m;
LL f[7][10];
int d[10];
LL solve(int p){
LL ret=0;
int k=0;
while(p){
d[++k]=p%10;
p/=10;
}
d[k+1]=0;
for(int i=k;i>=1;--i){
for(int j=d[i]-1;j>=0;--j)
if(d[i+1]!=6||j!=2)
ret+=f[i][j];
if(d[i]==4||(d[i+1]==6&&d[i]==2)) break;
}
return ret;
}
int main(){
for(int i=0;i<=9;++i)
if(i!=4) f[1][i]=1;
for(int i=2;i<=7;++i)
for(int j=0;j<=9;++j)
if(j!=4)
for(int k=0;k<=9;++k){
if(k==2&&j==6) continue;
f[i][j]+=f[i-1][k];
}
while(scanf("%d%d",&n,&m)&&(n+m)){
printf("%lld\n",solve(m+1)-solve(n));
}
return 0;
}