洛谷P1831 杠杆数
题目描述
如果把一个数的某一位当成支点,且左边的数字到这个点的力矩和等于右边的数字到这个点的力矩和,那么这个数就可以被叫成杠杆数。
比如4139就是杠杆数,把3当成支点,我们有这样的等式:4 2 + 1 1 = 9 * 1。
给定区间[x,y],求出在[x,y]中有几个杠杆数。
输入输出格式
输入格式:
两个数,表示x,y。
输出格式:
一个输出,表示区间[x,y]中杠杆数的个数。
输入输出样例
输入样例#1:
7604 24324
输出样例#1:
897
说明
对于40%的数据,x<=y<=x+100000
对于100%的数据,1<=x<=y<=10^18
#include<iostream> #include<cstdio> using namespace std; long long l,r,ans; int a[20]; bool check(long long now){ int len=0; while(now){ a[++len]=now%10; now/=10; } int L=0,R=0; for(int i=1;i<=len;i++){//枚举支点 L=0;R=0; for(int j=1;j<i;j++)L+=(i-j)*a[j]; for(int j=i+1;j<=len;j++)R+=(j-i)*a[j]; if(L==R)return 1; } return 0; } int main(){ scanf("%lld%lld",&l,&r); for(long long i=l;i<=r;i++){ if(check(i))ans++; } cout<<ans; }
/* 数位dp,写的记忆化搜索 应该算数位dp中的简单题吧,套路都在 */ #include<iostream> #include<cstdio> #include<cstring> using namespace std; long long a,b,dp[20][20][2005]; int bit[20],len; long long dfs(int pos,int central,int pre,int limit){ if(pos<=0)return pre==0; if(pre<0)return 0; if(!limit&&dp[pos][central][pre]!=-1)return dp[pos][central][pre]; int end=limit?bit[pos]:9; long long ans=0; for(int i=0;i<=end;i++){ ans+=dfs(pos-1,central,pre+i*(pos-central),limit&&i==end); } if(!limit)dp[pos][central][pre]=ans; return ans; } long long solve(long long x){ len=0; while(x){ bit[++len]=x%10; x/=10; } long long ans=0; for(int i=1;i<=len;i++)ans+=dfs(len,i,0,1); return ans-len+1; } int main(){ memset(dp,-1,sizeof(dp)); scanf("%lld%lld",&a,&b); printf("%lld",solve(b)-solve(a-1)); }