题目链接:https://vjudge.net/problem/HDU-3709
题意:求出[l,r]中的平衡数,平衡数即存在一个中心点使得两边的力矩和相等。
思路:首先需要知道一个数最多只有一个中心点,可以通过反证法轻松得出,所以我们可以对长为pos的数枚举其中心点。用dp[pos][m][sum]表示长为pos+1、中心点在第m位、现在的力矩和为sum的数的个数。中心点一边的力矩和最大大约为1500,所以离散化一下,用1500表示0。另外要注意的是每次枚举中心点都会将0算入,所以最后要减取多加的pos-1个0。
AC代码:
#include<cstdio> #include<cstring> using namespace std; typedef long long LL; const int key=1500; int T; LL a[20],dp[20][20][2*key]; LL dfs(int pos,int m,int sum,bool limit){ if(pos==-1) return sum==key; if(!limit&&dp[pos][m][sum]!=-1) return dp[pos][m][sum]; int up=limit?a[pos]:9; LL tmp=0; for(int i=0;i<=up;++i) tmp+=dfs(pos-1,m,sum+i*(pos-m),limit&&i==a[pos]); if(!limit) dp[pos][m][sum]=tmp; return tmp; } LL solve(LL x){ int pos=0; LL ans=0; while(x){ a[pos++]=x%10; x/=10; } for(int i=0;i<pos;++i) ans+=dfs(pos-1,i,key,true); return ans-pos+1; } int main(){ memset(dp,-1,sizeof(dp)); scanf("%d",&T); while(T--){ LL l,r; scanf("%lld%lld",&l,&r); printf("%lld ",solve(r)-solve(l-1)); } return 0; }