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;
}