B-number HDU - 3652 (数位DP)

题目链接:

B-number

 HDU - 3652 

题目大意:给你一个n,然后问你从1~n中有多少个数是能被13整除并且包含13的。

具体思路:dp[i][j][k]表示到第i位的时候,余数为0,并且凑成13的类型为k的时候的状态(0为之前的没有凑齐过13,1为之前只凑齐了1,2位之前凑齐了13)

数位DP求的就是一个前缀和?

AC代码:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 # define ll long long
 4 # define inf 0x3f3f3f3f
 5 const int maxn = 1100;
 6 int a[maxn];
 7 int dp[maxn][14][3];
 8 int check(int t1,int t2){
 9 if(t1==1&&t2!=1&&t2!=3)return 0;
10 if(t1==0&&t2==1)return 1;
11 if(t1==1&&t2==3)return 2;
12 return t1;
13 }
14 int dfs(int pos,int is_head,int mod,int is_13){
15 if(!pos)return mod==0&&is_13==2;
16 if(!is_head&&dp[pos][mod][is_13]!=-1)return dp[pos][mod][is_13];
17 int fmax = is_head ? a[pos]:9;
18 int ans=0;
19 for(int i=0;i<=fmax;i++){
20 ans+=dfs(pos-1,is_head&&i==fmax,(mod*10+i)%13,check(is_13,i));
21 }
22 if(!is_head)dp[pos][mod][is_13]=ans;
23 return ans;
24 }
25 int cal(int t){
26 int num=0;
27 memset(dp,-1,sizeof(dp));
28 while(t){
29 a[++num]=t%10;
30 t/=10;
31 }
32 return dfs(num,1,0,0);
33 }
34 int main(){
35 int n;
36 while(~scanf("%d",&n)){
37 printf("%d\n",cal(n));
38 }
39 return 0;
40 }

猜你喜欢

转载自www.cnblogs.com/letlifestop/p/10835109.html