BZOJ3598&&洛谷P3286 [SCOI2014]方伯伯的商场之旅

数位DP神题(至少我是这样认为的)

说一下抄来的思路

我们先假设平衡位置在第一位(最左边),然后算出现在的总代价,然后我们再枚举其他位置时的贡献差

自己模拟一下平衡位置右移过程中的变化,假设i是第p位且在现在的平衡点k的右侧,之前的贡献是i*(p-k+1),现在是i*(p-k),差值是一个i所以+i,反之亦然是-i,然后就没了

代码

//By AcerMo
#include
#include
#include
#include
#include
#define lli long long int 
using namespace std;
lli l,r,e;
lli lim[55],f[55][6000];
inline lli dfs(int p,lli sum,bool jud)
{
	if (!p) return sum;
	if (!jud&&f[p][sum]!=-1) return f[p][sum];
	lli ans=0;int emm=jud?lim[p]:e-1;
	for (int i=0;i<=emm;i++)
	ans+=dfs(p-1,sum+i*(p-1),jud&&(i==emm));
	if (!jud) return f[p][sum]=ans;
	return ans;
}
inline lli sub(int p,lli sum,int k,bool jud)
{
	if (sum<0) return 0;
	if (!p) return sum;
	if (!jud&&f[p][sum]!=-1) return f[p][sum];
	lli ans=0;int emm=jud?lim[p]:e-1;
	for (int i=0;i<=emm;i++)
	if (p>=k) ans+=sub(p-1,sum+i,k,jud&&(i==emm));
	else ans+=sub(p-1,sum-i,k,jud&&(i==emm));
	if (!jud) return f[p][sum]=ans;
	return ans;
}
inline lli slove(lli x)
{
	int len=0;
	while (x) lim[++len]=x%e,x/=e;
	memset(f,-1,sizeof(f));
	lli ans=dfs(len,0,1);
	for (int i=2;i<=len;i++) 
	{
		memset(f,-1,sizeof(f));
		ans-=sub(len,0,i,1);
	}
	return ans;
}
signed main()
{
	cin>>l>>r>>e;
	cout<

 

你可能感兴趣的:(动态规划,爆搜)