HDU 4389 X mod f(x) (数位DP)

题目链接  HDU4389

题意  给出T个区间[L, R],统计L到R中有多少个满足条件的数。

限制条件为该数能被这个数的各位数字之和整除。

数据范围$1 <= L <= R <= 10^{9}$

考虑数位DP

注意到f(x)最大为81,所以对1-81每一个和做一遍数位DP即可。

f[pos][mod][sum][x] 表示当前处理到第pos位,当前的数位和对x取模的结果,当前的数位和,以及当前正在求的x = f(x)

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b)	for (int i(a); i >= (b); --i)

int f[11][82][82][82];
int a[12];
int T;
int l, r;
int ca = 0;

int dp(int pos, int mod, int sum, int x, int flag){
	if (pos == 0) return x == sum && mod == 0;
	if (!flag && ~f[pos][mod][sum][x]) return f[pos][mod][sum][x];

	int ret = 0;
	int ed = flag ? a[pos] : 9;

	rep(i, 0, ed) ret += dp(pos - 1, (mod * 10 + i) % x, sum + i, x, flag && i == a[pos]);
	if (!flag) f[pos][mod][sum][x] = ret;
	return ret;
}

int solve(int x){
	int len = 0, ret = 0;
	for (; x; x /= 10) a[++len] = x % 10;
	rep(i, 1, 81) ret += dp(len, 0, 0, i, 1);
	return ret;
}

int main(){

	memset(f, -1, sizeof f);
	scanf("%d", &T);
	while(T--){
		scanf("%d%d", &l, &r);
		printf("Case %d: %d\n", ++ca, solve(r) - solve(l - 1));
	}
	return 0;
}
时间: 2024-10-25 05:41:46

HDU 4389 X mod f(x) (数位DP)的相关文章

hdu 4389 X mod f(x) 数位dp

题链:http://acm.hdu.edu.cn/showproblem.php?pid=4389 X mod f(x) Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2330    Accepted Submission(s): 919 Problem Description Here is a function f(x): int

HDU 4389——X mod f(x)(数位DP)

X mod f(x) Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description Here is a function f(x): int f ( int x ) {     if ( x == 0 ) return 0;     return f ( x / 10 ) + x % 10; } Now, you want to know, in a 

[数位dp] hdu 4389 X mod f(x)

题意:为[A,B] 区间内的数能刚好被其位数和整除的数有多少个. 思路:为了避免状态重复,枚举位数和1~81 dp[site][sum][mod][wsh] 到site位,位数和为sum,对最后位数和为wsh的余数为mod,最后位数和是wsh 枚举1~81 累计就是答案. 代码: #include"cstdlib" #include"cstdio" #include"cstring" #include"cmath" #incl

HDU X mod f(x) (数位DP)

题意:求一个区间内各位数字之和能被该数整除的个数. 析:数位DP,dp[i][j][k][l] 表示前 i 位和为 j,对 k 取模为 l,然后就好做了. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #include <cmath> #include

HDU 4389 X mod f(x)

X mod f(x) Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description Here is a function f(x): int f ( int x ) {    if ( x == 0 ) return 0;    return f ( x / 10 ) + x % 10; } Now, you want to know, in a gi

HDU - 4352 - XHXJ&#39;s LIS(数位DP)

链接: https://vjudge.net/problem/HDU-4352 题意: a 到 b中一个数组成递增子序列长度等于k的数的个数 思路: 因为只有10个数,使用二进制维护一个递增序列,每次更新在注释写了. 然后正常的数位DP, Dp(i, j, k),i是位置,j是当前的递增状态,k是长度. 考虑一下前缀0,重置状态 代码: #include<bits/stdc++.h> using namespace std; typedef long long LL; const int MO

HDU - 2089 不要62 (暴力或数位DP)

Description 杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer). 杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍,更安全地服务大众. 不吉利的数字为所有含有4或62的号码.例如: 62315 73418 88914 都属于不吉利号码.但是,61152虽然含有6和2,但不是62连号,所以不属于不吉利数字之列. 你的任务是,对于每次给出的一个牌照区间号,推断出交管局今次又要实际上给多少辆新

HDU 4352 XHXJ&#39;s LIS (数位DP,状压)

题意: 前面3/4的英文都是废话.将一个正整数看成字符串,给定一个k,问区间[L,R]中严格的LIS=k的数有多少个? 思路: 实在没有想到字符0~9最多才10种,况且也符合O(nlogn)求LIS的特点,所以用状态压缩可以解决. 看到状态压缩的字眼基本就会做了,增加一维来保存当前LIS的状态.由于求LIS时的辅助数组d[i]表示长度为i的LIS最后一个元素,d数组是严格递增的,所以好好利用d数组的特性来设计状态压缩才是关键.压缩的状态0101可以表示:仅有0和2在数组d中,即d[1]=0,d[

HDU 5642 King&#39;s Order(数位DP)

题目链接:点击打开链接 题意:要求你生成一个合法的字符串, 由小写字母a~z组成, 相同字母相邻出现不能超过3个, 求有多少种组合. 思路:数位DP来做, 用d[i][j][k]表示处理完前i个字母, 第i-1个字母为j,已经连续出现了k次的方法数. 然后每次转移就很简单了, 继续选择字母j(if(k < 3)), 或者换其他的. 细节参见代码: #include<cstdio> #include<cstring> #include<algorithm> #inc