數位dp詳解及模板
阿新 • • 發佈:2019-01-02
數位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;
}