数位dp合集w

【BZOJ1026】【SCOI2009】windy数

传送门~:http://www.lydsy.com/JudgeOnline/problem.php?id=1026

数位dp傻题QaQ

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <iostream>
 5 using namespace std;
 6 int f[15][15], A, B, da[15];
 7 void get_ready(){
 8     for (int i = 0; i <= 9; i++) f[1][i] = 1; 
 9     for (int i = 2; i <= 10; i++){
10         for (int j = 0; j <= 9; j++) {
11             for (int k = 0; k <= 9; k++) {
12                 if (abs(j-k) >= 2)    f[i][j] += f[i-1][k];
13             }
14         }
15     }
16 }
17 
18 int calc(int a){
19     if (a == 0) return 0;
20     int ret = 0, len = 0;
21     do{
22         da[++len] = a % 10;
23         a /= 10;
24     }while(a);
25     for (int i = 1; i < len; i++)
26         for (int j = 1; j <= 9; j++)
27             ret += f[i][j];
28     for (int i = 1; i < da[len]; i++) ret += f[len][i];
29     for (int i = len-1; i > 0; i--) {
30         for (int j = 0; j < da[i]; j++)
31             if (abs(j-da[i+1]) >= 2) ret += f[i][j];
32         if (abs(da[i]-da[i+1]) < 2) break;
33     }
34     return ret;
35 }
36 
37 int main(){
38     freopen("bzoj1026.in", "r", stdin);
39     freopen("bzoj1026.out", "w", stdout);
40     get_ready();
41     scanf("%d%d", &A, &B);
42     printf("%d\n", calc(B+1) - calc(A));
43     return 0;
44 }
_(:з」∠)_

 

【HDU3652】B-number

传送门:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=12990

题意:问1~n中包含"13"序列且能被13整除的数有多少个。

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <iostream>
 5 
 6 using namespace std;
 7 int n, da[30];
 8 int f[15][3][15], vis[15][3][15];
 9 
10 int dp(int len, int up, int type, int mod){
11     if (!len) return (!mod && type == 2);
12     if (!up && vis[len][type][mod]) return f[len][type][mod];
13     int ret = 0, top = up ? da[len] : 9;
14     for (int i = 0; i <= top; i++){
15         int x = type;
16         if (type == 0 && i == 1) x = 1;
17         if (i != 1 && type == 1) x = 0;
18         if (type == 1 && i == 3) x = 2;
19         ret += dp(len-1, up&&(i==top), x, (mod*10 + i)%13);
20     }
21     if (!up){
22         vis[len][type][mod] = 1;
23         f[len][type][mod] = ret;
24     }
25     return ret;
26 }
27 
28 int calc(int a){
29     int len = 0;
30     while (a){
31         da[++len] = a % 10;
32         a /= 10;
33     }
34     return dp(len, 1, 0, 0);
35 }
36 
37 int main(){
38     freopen("hdu3652.in", "r", stdin);
39     freopen("hdu3652.out", "w", stdout);
40     int l = 0;
41     while (~scanf("%d", &n)){
42         memset(f, 0, sizeof(f));
43         memset(vis, 0, sizeof(vis));
44         printf("%d\n", calc(n));
45     }
46 //    for (int i = 1; i <= 10010; i++)
47 //        cout<<i<<" "<<calc(i)<<" "<<i%p<<endl;
48     return 0;
49 }
View Code

 

 

【HDU3709】Balanced Number

传送门:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=41280

题意:题目先给出平衡数的概念:数n以数n中的某个位为支点,每个位上的数权值为(数字xi*(posi - 支点的posi)),如果数n里有一个支点使得所有数权值之和为0那么她就是平衡数。比如4139,以3为支点,左边 = 4 * (4 - 2) + 1 * (3 - 2) = 9,右边 = 9 * (1 - 2) = -9,左边加右边为0,所以4139是平衡数。现在给出一个区间[l,r],问区间内平衡数有多少个?

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <iostream>
 5 #define LL long long
 6 using namespace std;
 7 int da[20];
 8 LL l, r;
 9 LL f[20][20][2100];
10 
11 LL dp(int len, int pos, int up, int l){
12     if (!len || l < 0) return l == 0;
13     if (!up && f[len][pos][l] != -1) return f[len][pos][l];
14     LL ret = 0ll;
15     int top = up ? da[len] : 9;
16     for (int i = 0; i <= top; i++) {
17         ret += dp(len-1, pos, up&&(i==top), l+(len-pos)*i);
18     }
19     if (!up) f[len][pos][l] = ret;
20     return ret;
21 }
22 
23 LL calc(LL a){
24     int len = 0;
25     LL ret = 0ll;
26     while(a){
27         da[++len] = (int) (a % 10);
28         a /= 10ll;
29     }
30     for (int i = 1; i <= len; i++) {
31         ret += dp(len, i, 1, 0);
32     }
33     return ret-(LL)len+1;
34 }
35 
36 int main(){
37     freopen("hdu3709.in", "r", stdin);
38     freopen("hdu3709.out", "w", stdout);
39     int T;
40     scanf("%d", &T);
41     memset(f, -1, sizeof(f));
42     while (T--){
43         scanf("%lld%lld", &l, &r);
44         printf("%lld\n", calc(r) - calc(l-1));
45     }
46     return 0;
47 }
View Code

 

【HDU3886】 Final Kichiku “Lanlanshu”

传送门:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=21534

题意:A,B之间有多少个数,满足给定字符串的趋势,字符串由“/”“-”“\”这3个字符构成,分别表示上升,不变和下降。

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <iostream>
 5 using namespace std;
 6 const int p = 1e8;
 7 char ca[110], cb[110], c[110];
 8 int lenK, lenC;
 9 int da[110], K[110];
10 int f[110][110][10];
11 
12 bool getk(char s, int i, int las){
13     if (s == '-') return i == las;
14     if (s == '/') return i > las;
15     if (s == '\\') return i < las;
16     return 0;
17 }
18 
19 int dp(int len, int up, int zero, int k, int las){
20     //cout<<k<<endl;
21     if (!len) return k == lenK;
22     if (!up && !zero && f[len][k][las]!=-1) return f[len][k][las];
23     int ret = 0, top = up ? da[len] : 9;
24     for (int i = 0; i <= top; i++){
25         if (zero) {
26             if (!i) ret += dp(len-1, up&&(i==top), 1, 0, -1), ret %= p;
27             else ret += dp(len-1, up&&(i==top), 0, 0, i), ret %= p;
28         }
29         else {
30             if(getk(c[k], i, las) && k < lenK)
31                 ret += dp(len-1, up&&(i==top), 0, k+1, i), ret %= p;
32             else if((k > 0 && getk(c[k-1], i, las)))
33                 ret += dp(len-1, up&&(i==top), 0, k, i), ret %= p;    
34         }
35     }
36     if (!up && !zero) f[len][k][las] = ret;
37     return ret;
38 }
39 
40 int calc(char *ch, int x){
41     int len = strlen(ch);
42     for (int i = 0; i < len; i++) da[len-i] = ch[i]-'0';
43     while (!da[len] && len > 1) len--;
44     if (len == 1 && !da[len]) return 0;
45     if (x) {
46         da[1]--;
47         for (int i = 1; i < len; i++)
48             if (da[i] < 0) da[i] += 10, da[i+1]--;
49         while (!da[len] && len > 1) len--;
50     }
51     if (len == 1 && !da[len]) return 0;
52     //cout<<dp(len, 1, 1, 1, -2)<<endl;
53     return dp(len, 1, 1, 0, -1);
54 }
55 
56 int main(){
57     freopen("hdu3886.in", "r", stdin);
58     freopen("hdu3886.out", "w", stdout);
59     while (~scanf("%s%s%s",c, ca, cb)){
60         memset(f, -1, sizeof(f));
61         lenK = strlen(c);
62         printf("%08d\n",(calc(cb, 0) - calc(ca, 1) + p) % p);
63     }
64     return 0;
65 }
View Code

 

【HDU3943】K-th nya number

传送门:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=22331

题意:求出区间 (P,Q] 中找到第K个满足条件的数,条件是该数包含X个4和Y个7。

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <iostream>
 4 #define MaxN 110
 5 #define LL long long
 6 using namespace std;
 7 LL p, q, ls;
 8 LL f[30][2][21][21];
 9 int da[30], x, y;
10 int vis[30][2][21][21];
11 
12 LL dp(int len, int up, int zero, int a, int b){
13     if (!len) return (!a && !b);
14     if (a < 0 || b < 0) return 0ll;
15     if (!up && vis[len][zero][a][b]) return f[len][zero][a][b];
16     LL ret = 0ll;
17     int top = up ? da[len] : 9;
18     if (zero) ret = dp(len - 1, 0, 1, a, b);
19     for (int i = zero; i <= top; i++){
20         ret += dp(len-1, up&&(i==top), 0, a-(i==4), b-(i==7));
21     }
22     if (!up){
23         f[len][zero][a][b] = ret;
24         vis[len][zero][a][b] = 1;
25     }
26     return ret;
27 }
28 
29 LL calc(LL a){
30     int len = 0;
31     while (a){
32         da[++len] = (int) (a % 10);
33         a /= 10ll;
34     }
35     return dp(len, 1, 1, x, y);
36 }
37 
38 void Solve(LL k){
39     LL l = p, r = q, mid;
40     while (l + 1 < r){
41         mid = (l + r) / 2;
42         if ((calc(mid)-ls) < k) l = mid;
43         else r = mid;    
44     }
45     if ((calc(r)-ls) == k) printf("%lld\n", r);
46     else printf("Nya!\n");
47 }
48 
49 int main(){
50     freopen("hdu3943.in", "r", stdin);
51     freopen("hdu3943.out", "w", stdout);
52     int T, query, l = 0;
53     LL k;
54     scanf("%d", &T);
55     while (T--){
56         scanf("%lld%lld%d%d", &p, &q, &x, &y);
57         scanf("%d", &query);
58         ls = calc(p);
59         printf("Case #%d:\n", ++l);
60         for (int i = 1; i <= query; i++) {
61             scanf("%lld", &k);
62             Solve(k);
63         }
64     }
65     return 0;
66 }
View Code

 

【HDU4352】XHXJ's LIS

传送门:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=30872

题意:问L到R,各位数字组成的最长上升子序列的长度为K的数的个数。

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <iostream>
 5 #define LL long long
 6 using namespace std;
 7 int T, k;
 8 int da[30];
 9 LL f[30][1<<10][11];
10 LL l, r;
11 
12 int gets(int s, int x){
13     for (int i = x; i <= 9; i++){
14         if (s & (1<<i)) return (s^(1<<i)) | (1<<x);
15     }
16     return s|(1<<x);
17 }
18 
19 int getk(int x){
20     int ret = 0;
21     while(x){
22         ret += x & 1;
23         x >>= 1;
24     }
25     return ret;
26 }
27 
28 LL dp(int len, int up, int zero, int s){
29     if (!len) return getk(s) == k;
30     if (!up && f[len][s][k] != -1) return f[len][s][k];
31     LL ret = 0ll;
32     int top = up ? da[len] : 9;
33     if (zero) ret = dp(len-1, 0, 1, 0);
34     for (int i = zero; i <= top; i++){
35         ret += dp(len-1, up&&(i==top), 0, gets(s, i));
36     }
37     if (!up) f[len][s][k] = ret;
38     return ret;
39 }
40 
41 LL calc(LL a){
42     int len = 0;
43     while (a){
44         da[++len] = (int) (a % 10);
45         a /= 10ll;
46     }
47     return dp(len, 1, 1, 0);
48 }
49 
50 int main(){
51     freopen("hdu4352.in", "r", stdin);
52     freopen("hdu4352.out", "w", stdout);
53     scanf("%d", &T);
54     memset(f, -1, sizeof(f));
55     for (int i = 1; i <= T; i++){
56         scanf("%lld%lld%d", &l, &r, &k);
57         printf("Case #%d: %lld\n", i, calc(r)-calc(l-1));
58     }
59     return 0;
60 }
View Code

 

【SCOI2014】【BZOJ3598】方伯伯的商场之旅

看这里看这里whttp://www.cnblogs.com/Lukaluka/p/5206022.html

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 #include <iostream>
 5 #define LL long long
 6 using namespace std;
 7 const int MaxN = 65;
 8 int u[MaxN], d[MaxN], LEN;
 9 LL l, r, k;
10 LL f[MaxN][2][2], g[MaxN][1600], ans[2333], sum[MaxN][2][2];
11 
12 LL dp(int len, int up, int down){
13     if (!len) { sum[len][up][down] = 1; return 0; }
14     if (f[len][up][down]!= -1) return f[len][up][down];
15     LL ret = 0ll, num = 0ll;
16     int top = up ? u[len] : (int)k-1, bot = down ? d[len] : 0;
17     for (int i = bot; i <= top; i++){
18         int p1 = (i==top)&&up, p2 = i==bot&&down;
19         ret += dp(len-1, p1, p2) + i*(len-1)*sum[len-1][p1][p2];
20         num += sum[len-1][p1][p2];
21     }
22     f[len][up][down] = ret, sum[len][up][down] = num;
23     return ret;
24 }
25 
26 LL calc(LL x, LL y){
27     int len = 0, len2 = 0;
28     while(x){
29         u[++len] = (int) (x%k);
30         x /= k;
31     }
32     while(y){
33         d[++len2] = (int) (y%k);
34         y /= k;
35     }
36     LEN = len;
37     return dp(len, 1, 1);
38 }
39 
40 LL dfs(int len, int up, int down, int p, int s){
41     if (!len) return (LL)s;
42     if (!up && !down && g[len][s] != -1) return g[len][s];
43     LL ret = 0;
44     int top = up ? u[len] :(int)k-1, bot = down ? d[len] : 0;
45     for (int i = bot; i <= top; i++){
46         int x = (len >= p ? 1 : -1), c = i==top&&up, d = i==bot&&down;
47         x = x*i + s;
48         if (x < 0) break;
49         ret += dfs(len-1, c, d, p, x);
50     }
51     if (!up && !down) g[len][s] = ret;
52     return ret;
53 }
54 
55 void Solve(){
56     memset(f, -1ll, sizeof(f));
57     LL ret = calc(r, l);
58     //cout<<ret<<endl;
59     LL dec = 0ll;
60     for (int i = 2; i <= LEN; i++){
61         memset(g, -1ll, sizeof(g)), dec += dfs(LEN, 1, 1, i, 0);
62     }
63     cout<<ret - dec;
64 }
65 
66 int main(){
67     cin>>l>>r>>k;
68     Solve();
69     return 0;
70 }
View Code

 

啊TuT待更

posted @ 2016-02-15 15:33  Lukaluka  阅读(470)  评论(9编辑  收藏  举报