#1791 : 幸运数字(数位dp)

43 篇文章 0 订阅
21 篇文章 0 订阅

描述

定义一个数字 x 是幸运的,当且仅当 x 是 x 十进制下所有数位的和的倍数

例如 1..9 所有数都是幸运数,120 也是幸运数

现在给定 n ,求 [1, n] 中有几个幸运数

输入

第一行一个正整数 n

1 ≤ n ≤ 1012

输出

输出有几个幸运数

样例输入

10

样例输出

10

这道题以前貌似做过,

思路:

如果直接dp,发现dp数组存不下sum,然后因为位数和最大为108,所以就可以枚举所有的位数和,分别跑dp,求解,这样取模后,数组就可以存下了。

注意sum_1 - i <0 剪枝.

代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+10;
const int INF=0x3f3f3f3f;
int mod;
ll dp[32][130][120][2];
ll a[30];
ll dfs(int pos,ll sum_1,ll sum_2,int limit)
{
    if(pos==-1){return (sum_1==0)&&(sum_2==0);}
    if(!limit&&dp[pos][sum_1][sum_2][limit]!=-1)return dp[pos][sum_1][sum_2][limit];
    ll ans=0;
    int end=limit?a[pos]:9;
    for(int i=0;i<=end;i++)
    {
        if(sum_1-i<0)break;
        ans+=dfs(pos-1,sum_1-i,(sum_2*10+i)%mod,limit&&(i==a[pos]));
    }
    if(!limit)dp[pos][sum_1][sum_2][limit]=ans;
    return ans;
}

ll go(ll x)
{
    int pos=0;
    while(x)
    {
        a[pos++]=x%10;
        x/=10;
    }
    ll ans=0;
    for(int i=1;i<=pos*9;i++)
    {
        memset(dp,-1,sizeof(dp));
        mod=i;
        ans+=dfs(pos-1,i,0,1);
    }
    return ans;
}
int main()
{
    ll n;
    memset(dp,-1,sizeof(dp));
    scanf("%lld",&n);
    cout<<go(n)<<endl;
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值