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 f ( int x ) {
       if ( x == 0 ) return 0;
       return f ( x / 10 ) + x % 10;
   }

   Now, you want to know, in a given interval [A, B] (1 <= A <= B <= 109), how many integer x that mod f(x) equal to 0.

Input

   The first line has an integer T (1 <= T <= 50), indicate the number of test cases.

   Each test case has two integers A, B.

Output

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

Sample Input

2
1 10
11 20

Sample Output

Case 1: 10
Case 2: 3

数位dp学习链接:http://blog.csdn.net/cyendra/article/details/38087573

题意:相当于问区间内有多少数满足 X%(∑xi)==0。∑xi 是数字X的数位和。

做法:由于最多9位数,所以能够枚举∑xi,最大为81。 然后就是数位dp了。

sum是数位和,nwmod是取模结果,mod 是枚举的模

当数位和sum==mod并且,nwmod最后==0,成立计数。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <malloc.h>
#include <ctype.h>
#include <math.h>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#include <stack>
#include <queue>
#include <vector>
#include <deque>
#include <set>
#include <map> 

typedef long long LL;
const int maxn=81;
int dig[maxn];
int f[10][maxn][maxn][maxn];
//nwmod  数取模后 sum 数位和
LL dfs(int pos,int nwmod,int sum,int mod,int limit)
{
	if (pos<0) return sum==mod&&nwmod==0;
	if (!limit&&f[pos][nwmod][sum][mod]!=-1)
		return f[pos][nwmod][sum][mod];
	LL res=0;
	int last=limit?dig[pos]:9;
	for (int i=0;i<=last;i++)
	{
		res+=dfs(pos-1,(nwmod*10+i)%mod,sum+i,mod,limit&&(i==last));
	}
	if (!limit) f[pos][nwmod][sum][mod]=res;
	return res;
}

LL solve(LL n){
	int len=0;
	while (n)
	{
		dig[len++]=n%10;
		n/=10;
	}
	LL ans=0;
	for(int i=1;i<=81;i++)//枚举最后的mod
	{
		ans+=dfs(len-1,0,0,i,1);
	}
	return ans;
}
int main()
{
	int n;
	int t;
	int cas=1;
	scanf("%d",&t);
	int a,b;
	memset(f,-1,sizeof f);
	while(t--)
	{
		scanf("%d%d",&a,&b);
		if(a>b)
			swap(a,b);
		printf("Case %d: %I64d\n",cas++,solve(b)-solve(a-1));
	}
	return 0;
}

/*
2
1 10
11 20 

Sample Output
Case 1: 10
Case 2: 3
*/
时间: 2024-10-10 14:47:08

hdu 4389 X mod f(x) 数位dp的相关文章

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> us

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