真是跪了,一看范围就不会往枚举的方向想,没想到真用枚举加剪枝了。。。-》——-》
解释一下代码中的上限:
例如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; }
原文:http://www.cnblogs.com/jie-dcai/p/4279367.html