2018 ACM上海大都会赛 J-Beautifule Number(数位DP应用)

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 ≤ 10^12).

输出描述:

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

示例1

输入

2
10
18

输出

Case 1: 10
Case 2: 12

题目大意:给出一个数,要求找出1-n满足:本身能够整除自身各位数之和,的数字的数量。

思路:看数据范围就知道这不是一道简单的题,10^12,这么大,要么是有规律要么是有特殊的方法,,,emmm,这道题做法属于数位DP,但之前没有接触过,需要恶补一下。关于数位DP的两篇论文:算法合集之《浅谈数位类统计问题》算法合集之《数位计数问题解法研究》,这2篇文章讲的非常好,但是对于我这种资质愚钝的人来说可能还是有点朦胧,翻翻大佬们的博客,其中有一位大佬表示:其实数位DP(或者说所有记忆化搜索)都是可以看做通过搜索来填满状态的值。神来之笔,好不妙哉。

该题代码如下:

#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<string>
using namespace std;
typedef long long LL;
int a[20];//各位上的数 
LL dp[13][105][150];        //dp[i][j][k]记录 第i位,前面数位之和为j,对某个mod的余数是k的状态下满足条件的个数
int mod;
LL dfs(int p,int s,int r,bool l)//p为当前位数
{
    if(p==-1) return (s==mod&&!r);//枚举的数是合法的 
    if(dp[p][s][r]!=-1&&l==false) return dp[p][s][r];//限制条件 
    int up;
    if(l==true) up=a[p];
    else
        up=9;
    LL res=0;
    for(int i=0;i<=up;++i)//枚举不同的情况 
	{
        if(i+s>mod) break;         //剪枝
        res+=dfs(p-1,s+i,(r*10+i)%mod,l==true&&i==a[p]);
    }
    if(l==false) dp[p][s][r]=res;//记忆化 
    return res;
}
LL solve(LL N)
{
    int p=0;
    LL x=N;
    while(x>0)
	{
        a[p++]=x%10;
        x/=10;
    }//各位存储 
    LL s=0;
    for(int i=1;i<=9*p;++i)//枚举膜数 
	{
        mod=i;                          
        memset(dp,-1,sizeof(dp));       //这里的dp数组记录的只是针对一种模数的状态,所以每次都要清空
        s+=dfs(p-1,0,0,true);
    }
    return s;
}//数位DP 
int main()
{
    LL n;
    int k=0,t;
    scanf("%d",&t);
    while(t--)
	{
        scanf("%lld",&n);
        printf("Case %d: %lld\n",++k,solve(n));
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/PleasantlY1/article/details/81449174