hdu 3652 B-number (带整除的数位dp )
题目链接 题意:给出n,问[1,n]中,满足包含“13”且这个数(不是各位的和)能被13整除的数的个数。 思路:依然是数位dp..不过有一个小tip。。
由于包含13的情况非常难考虑(包含一个“13”,两个“13”…..)
所以要从反面考虑,即不包含13的情况。
但是由于还有另一个条件。
做法是把能被13整除的数考虑成全集U,然后在U中做分划,一部分是含13的,另一部分是不含13的。
这样我们要求两个答案,一个是能被13整除的,另一个是能被13整除并且不含13的,相减即为题目所求。
1/* ***********************************************
2Author :111qqz
3Created Time :2016年03月16日 星期三 09时27分49秒
4File Name :code/hdu/3652.cpp
5************************************************ */
6
7#include <cstdio>
8#include <cstring>
9#include <iostream>
10#include <algorithm>
11#include <vector>
12#include <queue>
13#include <set>
14#include <map>
15#include <string>
16#include <cmath>
17#include <cstdlib>
18#include <ctime>
19#define fst first
20#define sec second
21#define lson l,m,rt<<1
22#define rson m+1,r,rt<<1|1
23#define ms(a,x) memset(a,x,sizeof(a))
24typedef long long LL;
25#define pi pair < int ,int >
26#define MP make_pair
27
28using namespace std;
29const double eps = 1E-8;
30const int dx4[4]={1,0,0,-1};
31const int dy4[4]={0,-1,1,0};
32const int inf = 0x3f3f3f3f;
33LL n;
34LL dp[20][15];
35LL dp2[20][2][15];
36int digit[20];
37
38
39LL dfs (int pos,int sum,bool limit)
40{
41 if (pos==0) return sum==0;
42
43 if (!limit&&dp[pos][sum]!=-1) return dp[pos][sum];
44
45 int mx = limit ? digit[pos]:9;
46
47 LL res = 0LL ;
48 for ( int i = 0 ; i <= mx ; i++)
49 {
50 res+=dfs(pos-1,(sum*10+i),limit&&i==mx);
51 }
52
53 if(!limit) dp[pos][sum] = res;
54 return res;
55}
56LL dfs2(int pos,bool preis1,int sum,bool limit)
57{
58 if (pos==0) return sum==0;
59
60 if (!limit&&dp2[pos][preis1][sum]!=-1) return dp2[pos][preis1][sum];
61
62 int mx = limit? digit[pos]:9;
63 LL res = 0 ;
64 for ( int i = 0 ; i <= mx ; i++)
65 {
66 if (preis1&&i==3) continue;
67 res+=dfs2(pos-1,i==1,(sum*10+i),limit&&i==mx);
68 }
69
70 if (!limit) dp2[pos][preis1][sum] = res;
71 return res;
72}
73
74LL solve ( LL n)
75{
76 ms(digit,0);
77
78 int len = 0;
79 while (n)
80 {
81 digit[++len] = n;
82 n/= 10;
83 }
84 return dfs(len,0,true)-dfs2(len,false,0,true); //在能被13整除的数里划分,减去不含“13”的,就是含“13”的。
85 //因为含“13”的情况太复杂了。。。
86}
87int main()
88{
89 #ifndef ONLINE_JUDGE
90 freopen("code/in.txt","r",stdin);
91 #endif
92
93 ms(dp,-1); //dp数组子啊外面清空就好。。。。因为dp数组是所有数据公用的啊。。。。
94 ms(dp2,-1);
95 while (~scanf("%lld",&n))
96 {
97 LL ans = solve (n);
98 printf("%lld\n",ans);
99 }
100
101 #ifndef ONLINE_JUDGE
102 fclose(stdin);
103 #endif
104 return 0;
105}