zoukankan      html  css  js  c++  java
  • 【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;
    }
  • 相关阅读:
    数据库性能测试---前阿里数据库团队资深DBA杨奇龙
    阿里云 MYSQL 与 PG(丁奇与德哥)
    RHEL6中ulimit的nproc限制
    Linux下文件描述符
    Linux中的文件描述符与打开文件之间的关系------------每天进步一点点系列
    5.6 太多分区引起OOM
    Linux lsof命令使用小结
    重现PHP Core的调用栈
    用GDB排查Python程序故障
    mysql 索引优化
  • 原文地址:https://www.cnblogs.com/Invictus-Ocean/p/13273635.html
Copyright © 2011-2022 走看看