洛谷P1831 杠杆数
数位$dp$:
我们设法求出对于每个数$x$,求出$0$~$x$的满足题意的方案数记为$sum[x]$,那么本题的答案自然是$sum[y]-sum[x-1]$
那么怎么求出方案数呢?
我们可以枚举支点位置,求出力矩和,满足条件就返回值,并且记录值(记忆化搜索),注意最后要考虑$0$的情况,因为每次搜索都会搜索到$000000.......$,所以答案要减去,代码如下:
#include<iostream> #include<cstdio> #include<cstring> #define N 21 #define ll long long using namespace std; ll x,y; ll f[N][N][2507]; int val[N]; ll Dfs(int pos,int o,ll state,bool limit) { if(!pos) return !state; if(!limit&&f[pos][o][state]!=-1) return f[pos][o][state]; int maxn=limit?val[pos]:9; ll ans=0; for(int i=0;i<=maxn;++i) ans+=Dfs(pos-1,o,state+i*(pos-o),limit&&(i==maxn)); if(!limit) f[pos][o][state]=ans; return ans; } ll Get(ll n) { int len=0; while(n) { val[++len]=n%10; n/=10; } ll ans=0; for(int i=1;i<=len;++i) ans+=Dfs(len,i,0,1); return ans-len+1; } signed main() { scanf("%lld%lld",&x,&y); memset(f,-1,sizeof(f)); printf("%lld",Get(y)-Get(x-1)); return 0; }