标签:数位dp
题链:http://acm.hdu.edu.cn/showproblem.php?pid=4389
Here is a function f(x):
   int f ( int x ) {
       if ( x == 0 ) return 0;
       return f ( x / 10 ) + x % 10;
   }
2 1 10 11 20
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 
*/
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:数位dp
原文地址:http://blog.csdn.net/u013532224/article/details/46816821