题意:
题目很明确就是求[li,ri]区间内的”平衡数“。
什么是平衡数:就是一个数(abcde),注意这是一个数,a是万位、b是千位....
你需要从这些位中找到其中一个位置,使得这个位置左右两边的力矩相等。
就比如你选的是b为平衡位置,那么左边的值就是a*(a距离b的距离)
右边的值就是c*(c距离b的距离)+d*(d距离b的距离)+e*(e距离b的距离)
题解:
最主要的也就是dp方程
dp[x][y][z]表示:在枚举到第x位,左边力矩与右边力矩之差为y,平衡位置为z
还有就是记得用long long
代码:
1 //错点1、 2 //原来我找的状态是dp[x][y][z]是在枚举第x位,平衡位置前的力矩是y,z代表这是平衡位置前还是后 3 //但是这个状态是错的,因为我没有考虑平衡位置后的值,这样的话假如平衡位置在第三位 4 //12345 5 //12356 6 //这两个值的答案就会放到一个位置 7 //可以把y的含义变成平衡位置前力矩和平衡位置后力矩的差,如果这个值小于0就直接返回0 8 //错点2、 9 //我的最后一个状态是不对的,因为对于一个数123456 10 //因为我是for循环枚举平衡位置的,假设从前往后枚举平衡位置,在枚举平衡位置2的时候得到的一个结果在轮到平衡位置 11 //3的时候会返回平衡位置2得结果 12 //可以把第三个状态改成平衡位置在哪个位置 13 #include<stdio.h> 14 #include<string.h> 15 #include<algorithm> 16 #include<iostream> 17 using namespace std; 18 const int maxn=805; 19 typedef long long ll; 20 ll v[20],dp[20][2000][20]; 21 ll dfs(ll pos,ll sum,bool limit,bool sta,ll digi) 22 { 23 if(sum<0) 24 { 25 //printf("%d %d** ",mod1,mod2); 26 return 0; 27 } 28 if(pos==-1) 29 { 30 if(sum==0) 31 return 1; 32 return 0; 33 } 34 if(!limit && dp[pos][sum][digi]!=-1) return dp[pos][sum][digi]; 35 ll up=limit?v[pos]:9; 36 ll tmp=0; 37 for(ll i=0;i<=up;++i) 38 { 39 //printf("%d ",i); 40 if(pos-digi>0 || pos-digi<0) 41 tmp+=dfs(pos-1,sum+(pos-digi)*i,limit && i==v[pos],sta,digi); 42 else tmp+=dfs(pos-1,sum,limit && i==v[pos],1,digi);//,printf("** "); 43 } 44 if(!limit) dp[pos][sum][digi]=tmp; 45 return tmp; 46 } 47 ll solve(ll ans) 48 { 49 ll pos=0; 50 while(ans) 51 { 52 v[pos++]=ans%10; 53 ans/=10; 54 } 55 ans=0; 56 for(ll i=0;i<=pos-1;++i) 57 { 58 ans+=dfs(pos-1,0,true,0,i); 59 } 60 return ans-pos; 61 } 62 int main() 63 { 64 ll t,l,r; 65 scanf("%lld",&t); 66 memset(dp,-1,sizeof(dp)); 67 while(t--) 68 { 69 70 scanf("%lld%lld",&l,&r); 71 printf("%lld ",solve(r)-solve(l-1)); 72 } 73 return 0; 74 }