• 【AHOI2009】同类分布 题解(数位DP)


    题目大意:求$[l,r]$中各位数之和能被该数整除的数的个数。$0leq lleq rleq 10^{18}$。

    ------------------------

    显然数位DP。

    搜索时记录$pos$表示当前位置,$sum$表示各位数字之和,$st$表示原数,$limit$表示最高位限制。(如果有时间我会写一篇博客学习数位DP,希望不要咕咕

    转移自然是$dfs(pos+1,sum+i,st*10+i)$

    但是一看数据范围,肯定不能这么搜,不然内存会炸。这时我们不妨考虑取模

    根据题目,我们发现:当$stmod sum==0$的时候,该数是合法的。所以我们不妨枚举$mod$,当$st==0且sum==mod$时返回$1$。一共$18$位数,共$162$种状态。

    代码:

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    int l,r,len,mod;
    int a[20],dp[20][200][200];
    inline int dfs(int pos,int sum,int st,int limit)//pos位置,sum各位数字和,st原数,limit最高位限制 
    {
        if (pos>len&&sum==0) return 0;
        if (pos>len) return st==0&&sum==mod?1:0;
        if (!limit&&dp[pos][sum][st]!=-1) return dp[pos][sum][st];
        int ret=0,res=limit?a[len-pos+1]:9;
        for (int i=0;i<=res;i++)
            ret+=dfs(pos+1,sum+i,(10ll*st+i)%mod,i==res&&limit);
        return limit?ret:dp[pos][sum][st]=ret;
    }
    inline int chai(int x)
    {
        len=0;
        while(x>0){
            a[++len]=x%10;
            x/=10;
        }
        int res=0;
        for (mod=1;mod<=9*len;mod++)
        {
            memset(dp,-1,sizeof(dp));
            res+=dfs(1,0,0,1);
        }
        return res;
    }
    signed main()
    {
        scanf("%lld%lld",&l,&r);
        printf("%lld",chai(r)-chai(l-1));
        return 0;
    }
  • 相关阅读:
    Spring中Quartz的配置
    通用表格打印1
    使用Lucene.Net实现全文检索
    DIV CSS 网页兼容全搞定 (IE6 IE7 IE8 IE9 火狐 谷歌)
    Code128 条码生成
    URL参数Base64解密和解密
    JQuery EasyUI 中文API
    linux 下mysql命令 (授权用户 和 基本操作)
    python操作MySQL数据库
    GridView分组,统计,排序的解决方案
  • 原文地址:https://www.cnblogs.com/Invictus-Ocean/p/13273635.html
Copyright © 2020-2023  润新知