zoukankan      html  css  js  c++  java
  • 【数位dp】Beautiful Numbers @2018acm上海大都会赛J

    Beautiful Numbers

    PROBLEM

    题目描述

    NIBGNAUK is an odd boy and his taste is strange as well. It seems to him that a positive integer number is beautiful if and only if it is divisible by the sum of its digits.
    We will not argue with this and just count the quantity of beautiful numbers from 1 to N.

    输入描述:

    The first line of the input is T(1≤ T ≤ 100), which stands for the number of test cases you need to solve.
    Each test case contains a line with a positive integer N (1 ≤ N ≤ 1012).

    输出描述:

    For each test case, print the case number and the quantity of beautiful numbers in [1, N].

    输入

    2
    10
    18

    输出

    Case 1: 10
    Case 2: 12

    MEANING

    t组测试用例,每组测试用例给一个整数n,询问从1到n中有多少数能被其各位数之和整除。

    SOLUTION

    对于每个整数n,找到从1到n的每个数的各位数和的最大值k。
    从1到k枚举各位数之和。
    对于每个各位数之和,相当于在1到n中找有多少数能整除这个和,且各位数之和等于这个和。这样就将问题分解成若干子问题。
    接下来就是数位dp套板子。具体可以看代码中的注释。

    CODE

    #define IN_PC() freopen("C:\Users\hz\Desktop\in.txt","r",stdin)
    #define IN_TEST() freopen("","r",stdin)
    #define IN_LB() freopen("C:\Users\acm2018\Desktop\in.txt","r",stdin)
    #define OUT_PC() freopen("C:\Users\hz\Desktop\out.txt","w",stdout)
    #define OUT_LB() freopen("C:\Users\acm2018\Desktop\out.txt","w",stdout)
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int INF = 0x3f3f3f3f;
    const int MAXN = 1010;
    
    ll dp[15][100][100];
    bool q[15][100][100];
    int b[15], tot;
    //pos:枚举到哪一位 sum:最高位到当前位的和 remain:当前枚举的数除以各位数和的余数
    ll dfs(int pos, int sum, int remain, int meiju, bool limit) {
        if(pos == 0) return (remain == 0) ? 1ll : 0;
        if(limit && q[pos][sum][remain]) return dp[pos][sum][remain];//记忆化搜索
        ll res = 0;
        int up = limit?9:b[pos];
        for(int i = 0; i <= up; i++) {
            if(i + sum <= meiju && i + sum + 9 * (pos - 1) >= meiju)
                res += dfs(pos-1, sum+i, (remain*10+i) % meiju, meiju, limit || (i!=b[pos]));
        }
        if(limit) {
            q[pos][sum][remain] = true;
            dp[pos][sum][remain] = res;
        }
        return res;
    }
    
    ll solve(ll num) {
        int sum = 0;
        tot = 0;
        while(num) {
            sum += num % 10;
            b[++tot] = num % 10;
            num /= 10;
        }
        int ret;
        if(tot == 1)ret = b[tot];
        else ret = b[tot] - 1 + (tot - 1) * 9;
        sum = max(sum, ret);//找到各位数之和的最大值
        ll ans = 0;
        for(int i = 1; i <= sum; i++) {//枚举各位数之和,解决子问题
            memset(dp, 0, sizeof dp);
            memset(q, 0, sizeof q);
            ans += dfs(tot, 0, 0, i, false);
        }
        return ans;
    }
    
    int main() {
    //    IN_PC();
        int T;
        scanf("%d", &T);
        for(int ca = 1; ca <= T; ca++) {
            ll n;
            scanf("%lld", &n);
            printf("Case %d: ", ca);
            printf("%lld
    ", solve(n));
        }
        return 0;
    }
    
  • 相关阅读:
    Elasticsearch常用命令
    Linux中使用systemctl操作服务、新建自定义服务
    Windows下安装MongoDB解压版
    Java执行cmd命令、bat脚本、linux命令,shell脚本等
    Ubuntu
    PostgreSQL删除数据库失败处理
    Ubuntu service 命令
    Ubuntu18修改/迁移mysql5.7数据存放路径
    攻防世界-web-ics-02(sql注入、ssrf、目录扫描)
    攻防世界-web-filemanager(源码泄漏、二次注入)
  • 原文地址:https://www.cnblogs.com/NeilThang/p/9430463.html
Copyright © 2011-2022 走看看