数位dp详解及模板
数位dp一般应用于:
求出在给定区间内,符合条件的数的个数.条件一般与数的大小无关,而与 数的组成有关.
比如说在HDU2089中, 让求区间内数中不有4
和62
的数字个数之和
对于此类问题,我们一般设数组,表示i位数,最高位是j的数,不含有62
和4
的数有多少个
对于上述不含有62
和4
的要求,递推式如下
换成代码就是:
if(j==4)
dp[i][j] = 0;
else{
for(int k=0;j<=9;k++){
if(j==6&&k==2)
continue;
dp[i][j] += dp[i-1][k];
}
}
到此,我们就能求对于所有能被10整除的满足条件的数的个数了
而对于任意数,只需要将其拆成的形式即可
然后求出和的个数,相减便是答案
#include <map>
#include <queue>
#include <cmath>
#include <cstdio>
#include <string>
#include <cstring>
#include <iostream>
#include <algorithm>
#define IN freopen("in.txt","r",stdin)
#define OUT freopen("out.txt","w",stdout)
#define IO do{\
ios::sync_with_stdio(false);\
cin.tie(0);\
cout.tie(0);}while(0)
using namespace std;
typedef long long ll;
const int maxn = 1e4+10;
const int MAXN = 1e6+10;
const int INF = 0x3f3f3f3f;
const int inf = 0x3f;
const double EPS = 1e-7;
const double Pi = acos(-1);
const int MOD = 1e9+7;
int dp[15][15];
int num[15];
void init()
{
dp[0][0] = 1;
for(int i=1; i<=9; i++)
for(int j=0; j<=9; j++)
{
if(j==4)
dp[i][j] = 0;
else
for(int k=0; k<=9; k++)
{
if(j==6&&k==2)
continue;
dp[i][j] += dp[i-1][k];
}
}
}
int ask(int x)
{
ll ans = 0;
int cnt = 0;
while(x)
num[++cnt] = x%10,x/=10;
num[cnt+1] = 0;
for(int i=cnt; i>=1; i--)
{
for(int j=0; j<num[i]; j++)
{
if(j==4||(j==2&&num[i+1]==6))
continue;
ans += dp[i][j];
}
if(num[i] == 4||(num[i]==2&&num[i+1]==6))
break;
}
return ans;
}
int main()
{
IO;
//IN;
int n,m;
init();
while(cin >> m >>n &&(n||m))
cout <<ask(n+1)-ask(m)<<endl;
return 0;
}