1. 程式人生 > >[動態規劃][數位dp]不要62

[動態規劃][數位dp]不要62

號碼 每次 type 交通 main cst spa 消息 put

Problem Description

杭州人稱那些傻乎乎粘嗒嗒的人為62(音:laoer)。
杭州交通管理局經常會擴充一些的士車牌照,新近出來一個好消息,以後上牌照,不再含有不吉利的數字了,這樣一來,就可以消除個別的士司機和乘客的心理障礙,更安全地服務大眾。
不吉利的數字為所有含有4或62的號碼。例如:
62315 73418 88914
都屬於不吉利號碼。但是,61152雖然含有6和2,但不是62連號,所以不屬於不吉利數字之列。
你的任務是,對於每次給出的一個牌照區間號,推斷出交管局今次又要實際上給多少輛新的士車上牌照了。

Input 輸入的都是整數對n、m(0<n≤m<1000000),如果遇到都是0的整數對,則輸入結束。

Output 對於每個整數對,輸出一個不含有不吉利數字的統計個數,該數值占一行位置。

Sample Input 1 100 0 0

Sample Output 80

思路:似乎可以暴力?稍微修改一下,假定n,m<1e12把;進行數位dp,設狀態f[i][j]表示位數為i,最高位為j的所有數中滿足題意的數有多少,則狀態轉移方程為:

if(j==4) f[i][j]=0

else if(j!=6) f[i][j]=sum{f[i-1][k]}(k=0,1,2,3,4,5,...,9)

else f[i][j]=sum{f[i-1][k] }(k=0,1,3,4,5,...,9)

那區間[0,n)中滿足題意的數就為sum{f[i][k]}(k=0~a[i]-1)(a[i]表示n的第i位數字),再減去其中包含的一些不吉利數的個數;

AC代碼:

#include <iostream>
#include<cstdio>
typedef long long ll;
using namespace std;

ll n,m;
ll dp[15][15];

void get_dp(){
  dp[0][0]=1;
  for(ll i=1;i<=12;i++){
    for(ll j=0;j<=9;j++){
        dp[i][j]
=0; if(j==4) continue; else{ for(ll k=0;k<=9;k++) dp[i][j]+=dp[i-1][k]; if(j==6) dp[i][j]-=dp[i-1][2]; } } } } ll len=0,a[15]; void depart(ll x){ len=0; while(x){ a[++len]=x%10; x/=10; } } ll cal(ll x){ depart(x);//將x的各個位拆開 ll ret=0; for(ll i=len;i>=1;i--){ if(i<len&&a[i+1]==4) break; if(i<len-1&&a[i+1]==2&&a[i+2]==6) break; for(ll j=a[i]-1;j>=0;j--){ if(i==len) ret+=dp[i][j]; else{ if(!(a[i+1]==6&&j==2)) ret+=dp[i][j]; } } } return ret; } int main() { while(scanf("%lld%lld",&n,&m)!=EOF&&(n||m)){ get_dp(); printf("%lld\n",cal(m+1)-cal(n)); } return 0; }

[動態規劃][數位dp]不要62