zoukankan      html  css  js  c++  java
  • HDU4389: X mod f(x) 数位DP

    计算区间内一个数字各位之和能整除该数字的个数

    d[l][i][j][k]表示前l位和为i模j的结果为k的数的个数,那么就有方程

    d[l+1][i+x][j][(k*10+x)%j] += d[l][i][j][k]

    预处理出d[l][i][j][k],再逐位统计即可

    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    using namespace std;
    
    int bit[10];
    int dp[10][82][82][82];
    //d[l][i][j][k]表示前l位和为i模j的结果为k的数的个数
    void set()
    {
        int i,j,k,l,x;
        for(i = 1; i<=81; i++)
            dp[0][0][i][0] = 1;
        for(l = 0; l<9; l++)
            for(i = 0; i<=l*9; i++)
                for(j = 1; j<=81; j++)
                    for(k = 0; k<j; k++)
                        for(x = 0; x<=9; x++)
                            dp[l+1][i+x][j][(k*10+x)%j] += dp[l][i][j][k];
    }
    
    int solve(int n)
    {
        if(!n)
            return 0;
        int ans,i,j,k,len;
        int sum,tem1,tem2,s,bit[10],r;
        len = sum = ans = 0;
        tem1 = tem2 = n;
        s = 1;
        while(tem1)
        {
            bit[++len] = tem1%10;
            tem1/=10;
            sum+=bit[len];//每位数之和
        }
        if(n%sum==0)//本身要先看是否整除
            ans++;
        for(i = 1; i<=len; i++)
        {
            sum-=bit[i];//将该位清0
            tem2/=10;
            s*=10;
            tem1 = tem2*s;
            for(j = 0; j<bit[i]; j++) //枚举该位的状况
            {
                for(k = sum+j; k<=sum+j+9*(i-1); k++) //该位与更高位的和,而比该位低的和择优9*(i-1)种
                {
                    if(!k)//和为0的状况不符合
                        continue;
                    r = tem1%k;//现在该数对各位和进行取余
                    if(r)
                        r = k-r;//余数大于0,那么k-dd得到的数肯定能被t整除
                    ans+=dp[i-1][k-sum-j][k][r];//加上个数
                }
                tem1+=s/10;//标记现在算到哪里,例如1234,一开始t是1230,然后1231,1232,1233,1234,接下来1200,就是1210,1220,1230
            }
        }
        return ans;
    }
    
    int main()
    {
        int T,l,r,cas = 1;
        set();
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&l,&r);
            printf("Case %d: %d
    ",cas++,solve(r)-solve(l-1));
        }
    
        return 0;
    }
  • 相关阅读:
    用Fusion Log诊断同一版本冲突问题解决
    SQLSERVER 切换数据库为单用户和多用户模式
    redis常用命令
    linq函数All,Any,Aggregate说明
    rabbitmq部署安装
    Centos7防火墙常用命令
    SQL SERVER添加表注释、字段注释
    Windows定时任务管理以及服务管理
    SQLServer 2008数据库查看死锁、堵塞的SQL语句
    SQLServer查询死锁
  • 原文地址:https://www.cnblogs.com/Aragaki/p/7578284.html
Copyright © 2011-2022 走看看