HDU 3709

真是跪了,一看范围就不会往枚举的方向想,没想到真用枚举加剪枝了。。。-》——-》

 

解释一下代码中的上限:

例如4567,当枚举最高位时,很明显不能超过4,所以有上限,但当最高位为3以下时,低位就是没有上限的,可以从0~9枚举。当之前的和<0,则后面的会更少,所以可以剪枝。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define LL __int64
using namespace std;

LL dp[20][20][2000];
LL a[25];


LL dfs(int len,int pos,LL pre,bool flag){
	if(len==0){
		return pre==0?1:0;
	}
	if(pre<0) return 0;
	if(!flag&&dp[len][pos][pre]!=-1)
	return dp[len][pos][pre];
	int up=flag?a[len]:9;
	LL res=0;
	for(int i=0;i<=up;i++){
		LL tmp=pre;
		tmp+=(len-pos)*i;
		res+=dfs(len-1,pos,tmp,flag&&i==up);
	}
	if(!flag)
	dp[len][pos][pre]=res;
	return res;
}

LL slove(LL x){
	LL t=x;
	int len=0;
	while(t){
		a[++len]=t%10;
		t/=10;
	}
	LL ans=0;
	for(int i=len;i;i--){
		ans+=dfs(len,i,0,true);
	}
	return ans-len+1;
}

int main(){
	int T; LL l,r;
	memset(dp,-1,sizeof(dp));
	scanf("%d",&T);
	while(T--){
		scanf("%I64d%I64d",&l,&r);
		printf("%I64d\n",slove(r)-slove(l-1));
	}
	return 0;
}

  

posted @ 2015-02-07 22:00  chenjunjie1994  阅读(171)  评论(0编辑  收藏  举报