HDU 4389 X mod f(x)

来源:互联网 发布:工业生产总值数据 编辑:程序博客网 时间:2024/05/22 09:43

题意:求[A,B]内有多少个数,满足x % f(x) == 0。


解法:数位DP。转化为ans = solve(b) - solve(a - 1)。设dp[i][sum][mod][r]表示长度为i,各位和为sum,模mod余r的数的个数。

当在数字后面新添加一位j时,则有dp[i + 1][sum + j][mod][(r * 10 + j) % mod] += dp[i][sum][mod][r]。

当一个数比n小时,一定是因为从某一位开始出现了当前位的数字比n当前位数字小的情况,从高到低枚举这种情况出现的位数,枚举这位的数字,枚举所有数字的和,即模,满足等式(num + j * 10 ^ i + r) % mod == 0时即符合情况,num为前i位确定时的数值。

for i len...1

for j 0...digit[i]

for mod 1...81

for r 0...mod - 1

if (当前已确定位数值 + j * 10 ^ i + r) % mod == 0

ans += dp[i - 1][mod - 前i位和 - j][mod][r]


代码:

#include<stdio.h>#include<iostream>#include<algorithm>#include<string>#include<string.h>#include<math.h>#include<limits.h>#include<time.h>#include<stdlib.h>#include<map>#include<queue>#include<set>#include<stack>#include<vector>#define LL long longusing namespace std;int dp[12][85][85][85] = {0};int f(int x){    if(x == 0) return 0;    return f(x / 10) + x % 10;}void init()//初始化{    for(int i = 0; i < 85; i++)        dp[0][0][i][0] = 1;    for(int i = 0; i < 9; i++)        for(int j = 0; j < 85; j++)            for(int k = 0; k < 85; k++)                for(int l = 0; l < k; l++)                    for(int m = 0; m < 10 && m + j < 85; m++)                        dp[i + 1][j + m][k][(l * 10 + m) % k] += dp[i][j][k][l];}int solve(int x){    int ans = 0;    if(x && (x % f(x) == 0))        ans++;    int digit[15] = {0};    int ten[15] = {0, 1, 0};    for(int i = 2; i <= 10; i++)        ten[i] = ten[i - 1] * 10;    int len = 1;    int tmp = x;    while(tmp)    {        digit[len++] = tmp % 10;        tmp /= 10;    }    int sum = 0;    int num = 0;    for(int i = len - 1; i >= 1; i--)//枚举位数    {        for(int j = 0; j < digit[i]; j++)            for(int k = 1; k < 85; k++)                for(int l = 0; l < k; l++)                    if((k >= (sum + j)) && ((num + j * ten[i] + l) % k == 0))                        ans += dp[i - 1][k - sum - j][k][l];        sum += digit[i];        num += digit[i] * ten[i];    }    return ans;}int main(){    init();    int T;    while(~scanf("%d", &T))    {        int cnt = 1;        while(T--)        {            int a, b;            scanf("%d%d", &a, &b);            printf("Case %d: %d\n", cnt++, solve(b) - solve(a - 1));        }    }}


0 0