洛谷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;
}

  

posted @ 2019-01-07 10:28  模拟退火  阅读(131)  评论(0编辑  收藏  举报