zoukankan      html  css  js  c++  java
  • 【数位dp】

    hdu5787

    问:L ~ R有多少个数是K-wolf Number?其中,K-wolf Number的定义是这个数在十进制下,任意相邻的K个字符没有相同的。

    dp[i][j][k]表示有i个空位可填,其中不能填j这个数字中所含有的字符,k = true(表示j有前导0)时,还不能填0.

     1 #include <bits/stdc++.h>
     2 #define ll long long
     3 #define pii pair<int, int>
     4 #define mp make_pair
     5 #define fi first
     6 #define se second
     7 using namespace std;
     8 const int N = 1e5+5;
     9 ll l, r;
    10 int k;
    11 ll dp[20][100001][2];
    12 int temp[20], tot;
    13 
    14 ll dfs(int pos, int w, bool tag, bool flag){
    15 
    16     if(!pos) return 1;
    17     if(flag&&~dp[pos][w][tag]) return dp[pos][w][tag];
    18     int Max = flag? 9: temp[pos];
    19 
    20     int ret[5], sum = 0, tmp = w;
    21     while(tmp)
    22         ret[sum++] = tmp%10, tmp /= 10;
    23     if(tag) ret[sum++] = 0;
    24 
    25     ll ans = 0;
    26     for(int i = 0; i <= Max; i++){
    27         bool tag2 = true;
    28         for(int j = 0; j < sum&&j < k-1; j++)
    29             if(ret[j] == i) tag2 = false;
    30         if(tag2){
    31             tmp = 0;
    32             int first = min(k-2, sum-1);
    33             for(int j = first; j >= 0; j--)
    34                 tmp = tmp*10+ret[j];
    35             bool tag3 = false;
    36             if(first >= 0&&ret[first] == 0) tag3 = true;
    37             ans += dfs(pos-1, tmp*10+i, tag3, flag||i != Max);
    38         }
    39     }
    40     if(flag) dp[pos][w][tag] = ans;
    41     //printf("dfs %d, %d, %d, %d %lld
    ", pos, w, tag*1, flag*1, ans);
    42     return ans;
    43 }
    44 
    45 ll solve(ll x){
    46     tot = 0;
    47     while(x){
    48         temp[++tot] = x%10;
    49         x /= 10;
    50     }
    51     return dfs(tot, 0, 0, 0);
    52 }
    53 int main(){
    54     while(cin >> l >> r >> k){
    55         memset(dp, -1, sizeof(dp));
    56         ll ans = solve(r)-solve(l-1);
    57         cout << ans << endl;
    58     }
    59     return 0;
    60 }
    View Code

    hdu3652

    问:1~n有多少个数含有连续的“13”并且能被13整除。

     1 #include <bits/stdc++.h>
     2 #define ll long long
     3 using namespace std;
     4 int dp[11][13][10][2];
     5 int temp[20], tot;
     6 
     7 int dfs(int pos, int mod, int pre, bool tag13, bool flag){
     8     if(!pos)
     9         return (mod == 0&&tag13);
    10     if(flag&&~dp[pos][mod][pre][tag13]) return dp[pos][mod][pre][tag13];
    11     int Max = flag? 9: temp[pos];
    12 
    13     int ans = 0;
    14     for(int i = 0; i <= Max; i++)
    15         ans += dfs(pos-1, (mod*10+i)%13, i, tag13||(pre == 1&&i == 3), flag||i != Max);
    16     if(flag) dp[pos][mod][pre][tag13] = ans;
    17     return ans;
    18 }
    19 
    20 int solve(int x){
    21     tot = 0;
    22     while(x){
    23         temp[++tot] = x%10;
    24         x /= 10;
    25     }
    26     return dfs(tot, 0, 0, 0, 0);
    27 }
    28 int main(){
    29     memset(dp, -1, sizeof(dp));
    30     int n;
    31     while(cin >> n){
    32         ll ans = solve(n)-solve(0);
    33         cout << ans << endl;
    34     }
    35     return 0;
    36 }
    View Code

    hdu4734

    问:0~B中有多少数字各个数位权值和小于 f(A).

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 int lim;
     4 int dp[10][9<<9];
     5 int temp[20], tot;
     6 int dfs(int pos, int sum, bool flag){
     7     if(!pos)
     8         return 1;
     9     if(flag&&~dp[pos][sum]) return dp[pos][sum];
    10     int Max = flag? 9: temp[pos];
    11     int ans = 0;
    12     for(int i = 0; i <= Max; i++){
    13         if( (i<<(pos-1)) <= sum )
    14             ans += dfs(pos-1, sum-(i << (pos-1)), flag||i != Max);
    15     }
    16     if(flag) dp[pos][sum] = ans;
    17     return ans;
    18 }
    19 
    20 int solve(int x){
    21     tot = 0;
    22     while(x){
    23         temp[++tot] = x%10;
    24         x /= 10;
    25     }
    26     return dfs(tot, lim, 0);
    27 }
    28 int main(){
    29     memset(dp, -1, sizeof(dp));
    30     int t, a, b, ca = 1; scanf("%d", &t);
    31     while(t--){
    32         scanf("%d%d", &a, &b);
    33         lim = 0;
    34         for(int i = 0; a; i++){
    35             lim += (a%10)<<i;
    36             a /= 10;
    37         }
    38         // lim < (9*2^9)
    39         int ans = solve(b)-solve(0)+1;
    40         printf("Case #%d: %d
    ", ca++, ans);
    41     }
    42     return 0;
    43 }
    View Code

    hdu4507

    问:l~r中与7无关的数的平方和。与7无关的数定义为:不含数字7,不是7的倍数,且各位数和不是7的倍数。

     1 #include <bits/stdc++.h>
     2 #define ll long long
     3 using namespace std;
     4 const int P = 1e9+7;
     5 ll f[22];
     6 ll l, r;
     7 struct p{
     8     ll x, y, z;
     9     p(){}
    10     p(ll x, ll y, ll z):x(x), y(y), z(z){}
    11 };
    12 p dp[22][7][7];
    13 int temp[22], tot;
    14 void ad(ll& a, ll b){
    15     a += b;
    16     if(a < 0) a = a%P+P;
    17     if(a >= P) a %= P;
    18 }
    19 p dfs(int pos, int add, int mod, bool flag){
    20     if(!pos)
    21         return p(add&&mod, 0, 0);
    22     if(flag&&dp[pos][add][mod].x != -1) return dp[pos][add][mod];
    23 
    24     int Max = flag? 9: temp[pos];
    25     ll ans = 0, sum = 0, sum2 = 0;
    26     for(int i = 0; i <= Max; i++) if(i != 7){
    27         p ret = dfs(pos-1, (add+i)%7, (mod*10+i)%7, flag||i != Max);
    28         //i*10^(pos-1)+x
    29         ll tmp = f[pos-1]*i%P;
    30         ans += ret.x;
    31         ad(sum, (ret.y+ret.x%P*tmp)%P);
    32         ad(sum2, (ret.x%P*tmp%P*tmp%P+2*tmp*ret.y%P+ret.z)%P);
    33     }
    34     if(flag) dp[pos][add][mod] = p(ans, sum, sum2);
    35     //printf("pos %d, add %d, mod %d, flag %d: %lld %lld %lld
    ", pos, add, mod, flag*1, ans, sum, sum2);
    36     return p(ans, sum, sum2);
    37 }
    38 
    39 
    40 ll solve(ll x){
    41     tot = 0;
    42     while(x){
    43         temp[++tot] = x%10;
    44         x /= 10;
    45     }
    46     return dfs(tot, 0, 0, 0).z;
    47 }
    48 int main(){
    49     f[0] = 1;
    50     for(int i = 1; i <= 20; i++) f[i] = f[i-1]*10%P;
    51     memset(dp, -1, sizeof(dp));
    52     int t, a, b, ca = 1; scanf("%d", &t);
    53     while(t--){
    54         scanf("%lld%lld", &l, &r);
    55         ll ans = solve(r)-solve(l-1);
    56         ans %= P;
    57         if(ans < 0) ans += P;
    58         printf("%lld
    ", ans);
    59     }
    60     return 0;
    61 }
    View Code

    hdu3709

    问:l~r中有多少数字是平衡数? 平衡数的定义为能在数字中找到某一个点作为支点使左边的力矩和右边的力矩相等?如4139,以3为支点时左边是4*2+1*1 = 9, 右边是9*1 = 9.

     1 #include <bits/stdc++.h>
     2 #define ll unsigned long long
     3 using namespace std;
     4 ll dp[22][22][600+600];
     5 ll l, r;
     6 
     7 int temp[22], tot;
     8 
     9 ll dfs(int pos, bool pre, int pivot, int now, bool flag){
    10     if(!pos)
    11         return now == 0;
    12     if(flag&&~dp[pos][pivot][600+now]) return dp[pos][pivot][600+now];
    13 
    14     int Max = flag? 9: temp[pos];
    15     ll ans = 0;
    16     for(int i = 0; i <= Max; i++){
    17         if(!pre&&pivot == pos&&!i) continue ;
    18         int ret = now+(pos-pivot)*i;
    19         if(ret > 550||ret < -550) continue ;
    20         ans += dfs(pos-1, pre||i, pivot, ret, flag||i != Max);
    21     }
    22 
    23     if(flag) dp[pos][pivot][600+now] = ans;
    24     return ans;
    25 }
    26 
    27 
    28 ll solve(ll x){
    29     tot = 0;
    30     while(x){
    31         temp[++tot] = x%10;
    32         x /= 10;
    33     }
    34     ll ans = 0;
    35     for(int i = 1; i <= tot; i++)
    36         ans += dfs(tot, 0, i, 0, 0);
    37     return ans;
    38 }
    39 int main(){
    40     memset(dp, -1, sizeof(dp));
    41     int t, ca = 1; scanf("%d", &t);
    42     while(t--){
    43         cin >> l >> r;
    44         ll ans = 0;
    45         if(l == 0) l++, ans++;
    46         ans += solve(r)-solve(l-1);
    47         cout << ans << endl;
    48     }
    49     return 0;
    50 }
    View Code

    SPOJ Balanced Numbers

    问:l~r有多少数字满足奇数数字出现偶数次偶数数字出现奇数次。

     1 #include <bits/stdc++.h>
     2 #define ll unsigned long long
     3 using namespace std;
     4 //3^10 = 59049
     5 ll f[11];
     6 ll dp[22][2][59050];
     7 ll l, r;
     8 
     9 int temp[22], tot;
    10 bool judge(int x){
    11     bool tag = true;
    12     while(x){
    13         int ret = x%3;
    14         if(ret){
    15             ret &= 1;
    16             if(ret != tag) return false;
    17         }
    18         tag = !tag;
    19         x /= 3;
    20     }
    21     return true;
    22 }
    23 ll dfs(int pos, bool pre, int now, bool flag){//pre == true 1
    24 //    printf("%d %d %d %d
    ", pos, pre*1, now, flag*1);
    25     if(!pos)
    26         return judge(now);
    27     if(flag&&~dp[pos][pre][now]) return dp[pos][pre][now];
    28 
    29     int Max = flag? 9: temp[pos];
    30     ll ans = 0;
    31     for(int i = 0; i <= Max; i++){
    32         int ret = 0;//3^j
    33         if(i||pre){
    34             ret = (now/f[i])%3;
    35             if(ret < 2) ret = now+f[i];
    36             else ret = now-f[i];
    37         }
    38         ans += dfs(pos-1, pre||i, ret, flag||i != Max);
    39     }
    40 
    41     if(flag) dp[pos][pre][now] = ans;
    42     //printf("pos %d, add %d, mod %d, flag %d: %lld %lld %lld
    ", pos, add, mod, flag*1, ans, sum, sum2);
    43     return ans;
    44 }
    45 
    46 
    47 ll solve(ll x){
    48     tot = 0;
    49     while(x){
    50         temp[++tot] = x%10;
    51         x /= 10;
    52     }
    53     return dfs(tot, 0, 0, 0);
    54 }
    55 int main(){
    56     f[0] = 1;
    57     for(int i = 1; i < 11; i++) f[i] = f[i-1]*3;
    58     memset(dp, -1, sizeof(dp));
    59     int t, ca = 1; scanf("%d", &t);
    60     while(t--){
    61         cin >> l >> r;
    62         ll ans = solve(r)-solve(l-1);
    63         cout << ans << endl;
    64     }
    65     return 0;
    66 }
    View Code

    hdu4352

    问:l~r有多少数字的严格最长上升子序列是k?

    题解:状压。dp[还剩i位][k][二进制位下的最长上升子序列]

     1 #include <bits/stdc++.h>
     2 #define ll unsigned long long
     3 using namespace std;
     4 const int N = 1e5+5;
     5 const int P = 1e9+7;
     6 ll dp[11][22][1<<11];
     7 ll l, r, k;
     8 
     9 int temp[22], tot;
    10 ll dfs(int pos, int k, int now, bool flag){
    11     if(!pos)
    12         return __builtin_popcount(now) == k;
    13     if(flag&&~dp[k][pos][now]) return dp[k][pos][now];
    14 
    15     int Max = flag? 9: temp[pos];
    16     ll ans = 0;
    17     for(int i = 0; i <= Max; i++) {
    18         if(!now&&!i) {
    19             ans += dfs(pos-1, k, now, flag||i != Max);
    20             continue ;
    21         }
    22         int ret = now;
    23         if( !((ret>>i)&1) ){//ret[i] : 0
    24             if( ret>>i ){
    25                 for(int j = i+1; j; j++)
    26                     if((ret>>j)&1){
    27                         ret ^= 1<<j;
    28                         break;
    29                     }
    30             }
    31             ret |= 1<<i;
    32         }
    33         ans += dfs(pos-1, k, ret, flag||i != Max);
    34     }
    35 
    36     if(flag) dp[k][pos][now] = ans;
    37     return ans;
    38 }
    39 
    40 
    41 ll solve(ll x){
    42     tot = 0;
    43     while(x){
    44         temp[++tot] = x%10;
    45         x /= 10;
    46     }
    47     return dfs(tot, k, 0, 0);
    48 }
    49 int main(){
    50     memset(dp, -1, sizeof(dp));
    51 
    52     int t, ca = 1; scanf("%d", &t);
    53     while(t--){
    54         cin >> l >> r >> k;
    55         ll ans = solve(r)-solve(l-1);
    56         printf("Case #%d: ", ca++);
    57         cout << ans << endl;
    58     }
    59     return 0;
    60 }
    View Code

    Codeforces 55D

    问:l~r有多少数字可以被各个位上的非0数字整除?

     1 #include <bits/stdc++.h>
     2 #define ll unsigned long long
     3 using namespace std;
     4 const int P = 2520;
     5 ll dp[20][1<<7][2550];
     6 ll l, r;
     7 int w[10][4] = {
     8     {0, 0, 0, 0},
     9     {0, 0, 0, 0},
    10     {1, 0, 0, 0},
    11     {0, 1, 0, 0},
    12     {2, 0, 0, 0},
    13     {0, 0, 1, 0},
    14     {1, 1, 0, 0},
    15     {0, 0, 0, 1},
    16     {3, 0, 0, 0},
    17     {0, 2, 0, 0}
    18 };
    19 int temp[22], tot;
    20 ll dfs(int pos, int k, int now, bool flag){
    21     //printf("%d %d %d
    ", pos, k, now);
    22     if(!pos){
    23         int a2 = k&3, a3 = (k>>2)&3, a5 = (k>>4)&1, a7 = k>>5;
    24         if(a2 == 1&&now%2) return 0;
    25         if(a2 == 2&&now%4) return 0;
    26         if(a2 == 3&&now%8) return 0;
    27         if(a3 == 1&&now%3) return 0;
    28         if(a3 == 2&&now%9) return 0;
    29         if(a5&&now%5) return 0;
    30         if(a7&&now%7) return 0;
    31         return 1;
    32     }
    33     if(flag&&~dp[pos][k][now]) return dp[pos][k][now];
    34 
    35     int Max = flag? 9: temp[pos];
    36     ll ans = 0;
    37     int ret[4], ret2[4];
    38     ret[0] = k&3, ret[1] = (k>>2)&3, ret[2] = (k>>4)&1, ret[3] = k>>5;
    39     for(int i = 0; i <= Max; i++) {
    40         for(int j = 0; j < 4; j++)
    41             ret2[j] = max(ret[j], w[i][j]);
    42         int r = ret2[0]+(ret2[1]<<2)+(ret2[2]<<4)+(ret2[3]<<5);
    43         ans += dfs(pos-1, r, (now*10+i)%2520, flag||i != Max);
    44     }
    45 
    46     if(flag) dp[pos][k][now] = ans;
    47     //printf("%d %d %d: %lld
    ", pos, k, now, ans);
    48     return ans;
    49 }
    50 
    51 
    52 ll solve(ll x){
    53     tot = 0;
    54     while(x){
    55         temp[++tot] = x%10;
    56         x /= 10;
    57     }
    58     return dfs(tot, 0, 0, 0);
    59 }
    60 int main(){
    61     memset(dp, -1, sizeof(dp));
    62     int t, ca = 1; scanf("%d", &t);
    63     while(t--){
    64         cin >> l >> r;
    65         ll ans = solve(r)-solve(l-1);
    66         cout << ans << endl;
    67     }
    68     return 0;
    69 }
    View Code
  • 相关阅读:
    jquery.cookie.js
    CSS实现三角形
    关于seajs模块化的搭建
    浏览器版本类型及版本
    js || 和 &&
    bootstraps字体图标无法显示
    Thymeleaf的一些操作
    C语言I博客作业02
    C语言I博客作业03
    20169306《网络攻击与防范》第二周学习总结
  • 原文地址:https://www.cnblogs.com/dirge/p/6028794.html
Copyright © 2011-2022 走看看