zoukankan      html  css  js  c++  java
  • HDU 3652 B-number 数位DP

    http://acm.hdu.edu.cn/showproblem.php?pid=3652

    首先先解决怎么判断它是否含有13这个子串。

    方法就类似于一个状态记录dp

    加多一维[0 or 1]判断是否已经含有了13这个子串,那么如果枚举的时候,相邻的两位是13,则可由0跳转去1

    这题是设dp[i][j][0 or 1][r]表示i位数,以j为开头的,是否含有13这个子串了,然后余数是r( % 13)

    至于为什么要加上余数这个条件,

    是因为在统计答案的过程中,统计答案的方法和上一篇类似。有些不同的就是需要用余数来判断这一位应该加上那些数字。

    因为它是拆分开来的,按位dp

    比如26XX,那么XX后面的余数应该是0,这样才能整除以13

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <assert.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    #include <bitset>
    int n;
    int dp[12][12][2][15];
    LL base[15];
    void init() {
        base[0] = 1;
        for (int i = 1; i <= 10; ++i) {
            base[i] = base[i - 1] * 10;
        }
        for (int i = 0; i <= 9; ++i) {
            dp[1][i][0][i] = 1;
        }
        for (int i = 2; i <= 10; ++i) { //枚举一共有i位
            for (int j = 0; j <= 9; ++j) { //枚举第i位
                for (int x = 0; x <= 9; ++x) { //第i - 1位
                    int t = base[i - 1] * j % 13;
                    for (int r = 0; r <= 12; ++r) {
                        dp[i][j][1][(r + t) % 13] += dp[i - 1][x][1][r];
                        if (j == 1 && x == 3) {
                            dp[i][j][1][(r + t) % 13] += dp[i - 1][x][0][r];
                        } else {
                            dp[i][j][0][(r + t) % 13] += dp[i - 1][x][0][r];
                        }
                    }
                }
            }
        }
    }
    void work() {
        n++;
        int digit[15] = {0};
        int lenstr = 0;
        while (n / 10 > 0) {
            digit[++lenstr] = n % 10;
            n /= 10;
        }
        digit[++lenstr] = n % 10;
        int ans = 0;
        int mod = 0;
        bool flag = false;
        for (int i = lenstr; i >= 1; --i) {
            for (int j = 0; j <= digit[i] - 1; ++j) {
                ans += dp[i][j][1][(13 - mod) % 13];
                if (flag || j == 3 && digit[i + 1] == 1) {
                    ans += dp[i][j][0][(13 - mod) % 13];
                }
            }
            if (digit[i] == 3 && digit[i + 1] == 1) {
                flag = true;
            }
            mod = (mod + digit[i] * base[i - 1]) % 13;
        }
        cout << ans << endl;
    }
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        init();
        while (cin >> n) work();
        return 0;
    }
    View Code
  • 相关阅读:
    spring-session+Redis实现Session共享
    SQLServer语法常用总结
    [PDFBox]后台操作pdf的工具类
    类加载器
    SQLServer常用分页方式
    Tesseract识别图片提取文字&字库训练
    AbstractQueuedSynchronizer的简单介绍
    CountDownLatch 闭锁、FutureTask、Semaphore信号量、Barrier栅栏
    Java线程实现的第三种方式Callable方式与结合Future获取返回值
    原子类型的使用&Unsafe&CAS
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6298528.html
Copyright © 2011-2022 走看看