题目的意思是询问[A,B]区间内,有多少个Balanced Number,每个Balanced Number符合以下条件:
将一个数按位拆分,存在一个位置mid,使得sigma(val[i]*(mid-i))=sigma(val[j]*(j-mid)) {i<mid,j>mid}
然后就是一脸数位dp的样子...
一开始的想法是枚举mid,因为分析了一下,除0以为的某个Balanced Number,一定只有一个位置符合条件。
然后接下来就脑残了,将数字拆成两半来dp,然后合并的时候死活合并不了。后来想了一下,瞬间觉得自己脑残了,根本就不用拆分。直接从后往前dp就行,没想好代码怎么写,就开始敲,真的很忧伤..
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include<map> #include<queue> #include<iostream> using namespace std; #define For(i,forN) for(int i=0;i<forN;i++) #define sf scanf #define pf printf #define mp make_pair #define _clr(x,y) memset(x,(y),sizeof(x)) typedef long long LL; const int Maxn=21,Maxl=1400,Maxe=Maxl; LL dp[2][Maxn][Maxl]; int num[Maxn],len; typedef long long LL; LL A,B; LL getAns(int mid) { _clr(dp,0); dp[0][len][0]=1;//0表示x<=val,1表示x>val for(int i=len-1;i>=0;i--) { int s=0,l=i-mid; for(int j=0;j<Maxe;j++) { for(int k=s;k<10;k++) { int tj=l*k+j; if(tj<Maxe && tj>=0) { if(k<num[i])//那么x一定小于val { dp[0][i][tj]+=dp[0][i+1][j]+dp[1][i+1][j]; } else if(k>num[i])//那么x一定大于val { dp[1][i][tj]+=dp[0][i+1][j]+dp[1][i+1][j]; } else { dp[0][i][tj]+=dp[0][i+1][j]; dp[1][i][tj]+=dp[1][i+1][j]; } } } } } return dp[0][0][0]; } LL cal(LL val) { if(val<0) return 0; if(val<10) return val+1; len=0; while(val) { num[len++]=val%10; val/=10; } reverse(num,num+len); LL ans=0; for(int i=0;i<len;i++) ans+=getAns(i); return ans-len+1; } int main() { int cas; cin>>cas; while(cas--) { cin>>A>>B; cout<<cal(B)-cal(A-1)<<endl; } }