题意:给一个区间,求区间内满足一定条件的数的个数。条件是,这个数不含4且不含连续的62。
思路:传说中的数位dp,dp数组打好了,统计那一部分调了好久才弄对,思路不清晰啊。。dp(i,j)表示i位的数,最大位为j,符合这种情况的数中有多少个符合条件。统计时,对每一位从0统计到该位-1。
比如345就是dp(3,0)+dp(3,1)+dp(3,2)+3打头的小于345的三位数中满足条件的数,因此不能再加上dp(3,3),必须交给dp(2,x)来处理,全部列出来是dp(3,0)+dp(3,1)+dp(3,2)+dp(2,0)+dp(2,1)+dp(2,2)+dp(2,3)+dp(1,0)+dp(1,1)+dp(1,2)+dp(1,3)+dp(1,4),具体见代码。
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <memory.h>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <ctype.h>
#include <sstream>
#define INF 1000000
#define ull unsigned long long
#define min3(a,b,c) min(a,min(b,c))
#define max3(a,b,c) max(a,max(b,c))
#define MAXN 100010
using namespace std;
int dp[10][10];
int main() {
dp[0][0]=1;
for(int i=1;i<8;i++){
for(int j=0;j<10;j++){
if(j==4){
dp[i][j]=0;
continue;
}
for(int k=0;k<10;k++){
if(!(j==6&&k==2))
dp[i][j]+=dp[i-1][k];
}
}
}
int l,r;
while(cin>>l>>r){
if(l==0&&r==0)break;
r++;//统计的是小于r的数,所以-1
string lstr,rstr;
stringstream ss,ss2;
ss<<l;
ss>>lstr;
ss2<<r;
ss2>>rstr;
int lcnt=0;
int rcnt=0;
for(int i=0;i<lstr.size();i++){
//只统计0~对应位-1
for(int j=0;j<lstr[i]-48;j++){
if(i!=0&&(lstr[i-1]=='6'&&j==2) )continue;
lcnt+=dp[lstr.size()-i][j];
}
//如果已经出现了不满足的情况,就不用往下统计了
if(lstr[i]=='4'||i>0&&(lstr[i-1]=='6'&&lstr[i]=='2') )break;
}
for(int i=0;i<rstr.size();i++){
for(int j=0;j<rstr[i]-48;j++){
if(i!=0&&(rstr[i-1]=='6'&&j==2) )continue;
rcnt+=dp[rstr.size()-i][j];
}
if(rstr[i]=='4'||i>0&&(rstr[i-1]=='6'&&rstr[i]=='2') )break;
}
cout<<rcnt-lcnt<<endl;
}
return 0;
}