hdu 3652 B-number(數位DP)
阿新 • • 發佈:2019-01-12
Description
A wqb-number, or B-number for short, is a non-negative integer whose decimal form contains the sub- string "13" and can be divided by 13. For example, 130 and 2613 are wqb-numbers, but 143 and 2639 are not. Your task is to calculate how many wqb-numbers from 1 to n for a given integer n.Input
Output
Print each answer in a single line.Sample Input
13 100 200 1000
Sample Output
1 1 2 2
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N = 20;
int dp[N][N][N], dit[N];
int dfs(int len,int mod,int have,int limit)
{
if(len<=0)
return mod==0 && have==2;
if(!limit&&dp[len][mod][have]!=-1)
return dp[len][mod][have];
int ans=0, k;
k=limit?dit[len]:9;
for(int i=0;i<=k;i++)
{
int modx=(mod*10+i)%13, havex=have;
if(have == 0 && i == 1)//末尾不是1,現在加入的是1
havex = 1;//標記為末尾是1
if(have == 1 && i != 1)//末尾是1,現在加入的不是1
havex = 0;//標記為末尾不是1
if(have == 1 && i == 3)//末尾是1,現在加入的是3
havex = 2;//標記為含有13
ans+=dfs(len-1,modx,havex,limit&&i==k);
}
if(!limit)
dp[len][mod][have]=ans;
return ans;
}
int solve(int x)
{
memset(dit,0,sizeof(dit));
int k=0;
while(x)
{
dit[++k]=x%10;
x/=10;
}
memset(dp,-1,sizeof(dp));
return dfs(k,0,0,1);
}
int main()
{
int l;
while(scanf("%d", &l)!=EOF&&l)
{
printf("%d\n",solve(l));
}
return 0;
}
借鑑:
- #include <stdio.h>
- #include <string.h>
- #include <algorithm>
- using namespace std;
- int bit[15];
- int dp[15][15][3];
- //dp[i][j][k]
- //i:數位
- //j:餘數
- //k:3種操作狀況,0:末尾不是1,1:末尾是1,2:含有13
- int dfs(int pos,int mod,int have,int lim)//lim記錄上限
- {
- int num,i,ans,mod_x,have_x;
- if(pos<=0)
- return mod == 0 && have == 2;
- if(!lim && dp[pos][mod][have] != -1)//沒有上限並且已被訪問過
- return dp[pos][mod][have];
- num = lim?bit[pos]:9;//假設該位是2,下一位是3,如果現在算到該位為1,那麼下一位是能取到9的,如果該位為2,下一位只能取到3
- ans = 0;
- for(i = 0; i<=num; i++)
- {
- mod_x = (mod*10+i)%13;//看是否能整除13,而且由於是從原來數字最高位開始算,細心的同學可以發現,事實上這個過程就是一個除法過程
- have_x = have;
- if(have == 0 && i == 1)//末尾不是1,現在加入的是1
- have_x = 1;//標記為末尾是1
- if(have == 1 && i != 1)//末尾是1,現在加入的不是1
- have_x = 0;//標記為末尾不是1
- if(have == 1 && i == 3)//末尾是1,現在加入的是3
- have_x = 2;//標記為含有13
- ans+=dfs(pos-1,mod_x,have_x,lim&&i==num);//lim&&i==num,在最開始,取出的num是最高位,所以如果i比num小,那麼i的下一位都可以到達9,而i==num了,最大能到達的就只有,bit[pos-1]
- }
- if(!lim)
- dp[pos][mod][have] = ans;
- return ans;
- }
- int main()
- {
- int n,len;
- while(~scanf("%d",&n))
- {
- memset(bit,0,sizeof(bit));
- memset(dp,-1,sizeof(dp));
- len = 0;
- while(n)
- {
- bit[++len] = n%10;
- n/=10;
- }
- printf("%d\n",dfs(len,0,0,1));
- }
- return 0;
- }