hdu 3652 "B-number"(数位DP)

传送门

 

参考博文:

  [1]:http://www.voidcn.com/article/p-drrnjrmy-wm.html

 

题意:

  找出区间内数中含有13的并且能被13整除的数的个数

题解:

  搜了好多博客,看到了一些关键词;

  其中一个就有"秦九韶算法",补了补秦九韶算法,再看一下参考博文的代码,感觉,和秦九韶算法关联不是太大;

  下面说说我的思路:

  假设 num = 121394 ,(num%13=0,且含有"13")

  num可写成 1*105+2*104+1*103+3*102+9*101+4;

  那么,将这个数任意拆分成两部分,例如 令 a = 1*105+2*104 , b=1*103+3*102+9*101+4;

  你会发现 a%13+b%13 = 13;

  (假设下标从0开始,最高为为 pos,从第 i 位置断开,[i+1,pos]组成的数为 a)

  那么,定义 dp[ i ][ j ][ k ]:

  dp[ i ][ j ][0]表示从pos到i+1位不含有"13"且 j = (13-a%13)的数的个数;

  dp[ i ][ j ][1]表示从pos到i+1位不含有"13"但是第i+1位是1且 j = (13-a%13)的数的个数 ;

  dp[ i ][ j ][2]表示从pos到i+1为含有"13"且 j =  (13-a%13) 的数的个数;

AC代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5 #define mem(a,b) memset(a,b,sizeof(a))
 6 
 7 int n;
 8 int digit[10];
 9 int dp[10][13][3];
10 
11 int quickPower(int a,int b)
12 {
13     int ans=1;
14     while(b)
15     {
16         if(b&1)
17             ans *= a;
18         a *= a;
19         b >>= 1;
20     }
21     return ans;
22 }
23 //s对应着0,1,2状态
24 int DFS(int curPos,int curNum,int s,bool limit)
25 {
26     if(curPos == -1)
27         return curNum%13 == 0 && s == 2 ? 1:0;
28 
29     //以 num = 121394 为例
30     //如果当前的 curPos 来到 3数字处,那么 curNum = 121
31     //而实际要算的是 13-121000%13,所以需要将curNum*1000,就是对应的quickPower()
32     int mod=13-curNum*quickPower(10,curPos+1)%13;
33     if(!limit&&dp[curPos][mod][s] != -1)
34         return dp[curPos][mod][s];
35 
36     int up=limit ? digit[curPos]:9;
37     int ans=0;
38     for(int i=0;i <= up;++i)
39     {
40         int t=0;
41         if(s == 2)
42             t=2;
43         else if(s == 1 && i == 3)
44             t=2;
45         else if(i == 1)
46             t=1;
47         ans += DFS(curPos-1,curNum*10+i,t,limit&&i==digit[curPos]);
48     }
49     if(!limit)
50         dp[curPos][mod][s]=ans;
51 
52     return ans;
53 }
54 int Solve(int x)
55 {
56     int k=0;
57     while(x)
58     {
59         digit[k++]=x%10;
60         x /= 10;
61     }
62     return DFS(k-1,0,0,true);
63 }
64 int main()
65 {
66     mem(dp,-1);
67     while(~scanf("%d",&n))
68         printf("%d\n",Solve(n));
69 
70     return 0;
71 }
View Code

 

posted @ 2019-03-29 10:01  HHHyacinth  阅读(124)  评论(0编辑  收藏  举报