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;
}

浙公网安备 33010602011771号