哈尔滨工程大学ACM预热赛 G题 A hard problem(数位dp)

链接:https://ac.nowcoder.com/acm/contest/554/G

Now we have a function f(x):
int f ( int x ) {
    if ( x == 0 ) return 0;
    return f ( x / 10 ) + x % 10;
}

For a given interval [A, B] (1 <= A <= B <= 10^9), calculate how many integer x that mod f(x) equal to 0.

输入描述:

The first line has one integer T (1 <= T <= 50), indicate the number of test cases.
Next T lines, Each line has one test case that has two integers A and B, separated by one blank space.

输出描述:

For each test case, output only one line containing the case number and an integer indicated the number of x.
示例1

输入

2
1 10
11 20

输出

Case 1: 10
Case 2: 3
 
题意:让你求从a到b 有多少个数 能被自己各个数位的和整除
思路:数位dp dp[][][][];一维记录数位长度,二维记录数位加和,三维记录实际数同余模,四维记录具体模数
其实最后一维的考虑 本身理解的也不是很透彻 本来的思路是在递归的过程中就把值对数位和求模 但是这个思路有个很明显的错误是你不知道当前的数字和你的数位和是否对应
注(如果有错误 欢迎指正 仅代表个人观点)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#define ll long long int
using namespace std;
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
int moth[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int dir[4][2]={1,0 ,0,1 ,-1,0 ,0,-1};
int dirs[8][2]={1,0 ,0,1 ,-1,0 ,0,-1, -1,-1 ,-1,1 ,1,-1 ,1,1};
const int inf=0x3f3f3f3f;
//const ll mod=1e9+7;
int bits[30];
ll dp[30][100][100][100];//一维记录数位长度,二维记录数位加和,三维记录实际数同余模,四维记录具体模数
int mod;
ll dfs(int len,bool ismax,int modd,int sum,bool have0,int mod){
    if(!len) return modd==0&&sum==mod; //符合条件的的数判断,当数位加和等于模数,且实际数对其取模后等于0说明符合条件 
    if(!ismax&&dp[len][modd][sum][mod]>=0) return dp[len][modd][sum][mod];
    int up=ismax?bits[len]:9;
    ll ans=0;
    for(int i=0;i<=up;i++){
        if(i+sum>mod) break; //加和超过遍历的取模数 剪枝 
        if(have0&&(i==0)){
            ans+=dfs(len-1,ismax&&i==up,0,0,have0,mod);
        }else{
            int temp=(modd*10+i)%mod;
            ans+=dfs(len-1,ismax&&i==up,temp,sum+i,have0&&(i==0),mod);
        }
    }
    if(!ismax) dp[len][modd][sum][mod]=ans;
    return ans;
}
ll solve(int n){
    int len=0;
    while(n){
        bits[++len]=n%10;
        n/=10;
    }
    ll ans=0;
    for(int i=1;i<=9*len;i++){
        ans+=dfs(len,true,0,0,true,i); //遍历每一种数位和,用作同余模的模数,当累加实际数取模为0时是符合条件的
    }
       return ans;
}
int main(){
    //ios::sync_with_stdio(false);
    int a,b;
    int t;
    memset(dp,-1,sizeof(dp));
    scanf("%d",&t);
    int w=0;
    while(t--){
        scanf("%d%d",&a,&b);
        printf("Case %d: %lld
",++w,solve(b)-solve(a-1));
    }
    return 0;
}
 
原文地址:https://www.cnblogs.com/wmj6/p/10651173.html