看到数据范围很容易想到数位
很容易想到枚举每一位作为最优点
我们可以发现对于一个数字 如果他的最优点确定了 那离最优点越远 花费越高
我们可以先将所有的数字全合并到第一个点(用数位DP求) 然后依次枚举从
这样暴力转移每一位向后一位的贡献就可以啦~
具体的看代码就很容易懂qaq
#include<bits/stdc++.h>
#define ll long long
#define cl(x) memset(x,0,sizeof x)
using namespace std;
inline ll read(){
ll x=0;scanf("%lld",&x);return x;
}
ll l,r,k,top,f[55][5555],q[55];
ll dfs1(int pos,ll sum,bool flag){
if(!pos) return sum;
if(!flag&&f[pos][sum]) return f[pos][sum];
ll ans=0,mx=flag?q[pos]:k-1;
for(int i=0;i<=mx;i++) ans+=dfs1(pos-1,sum+(pos-1)*i,flag&&i==mx);
if(!flag) f[pos][sum]=ans;
return ans;
}
ll dfs2(int pos,ll sum,int sit,bool flag){
if(sum<0) return 0;
if(!pos) return sum;
if(!flag&&f[pos][sum]) return f[pos][sum];
ll ans=0,mx=flag?q[pos]:k-1;
for(int i=0;i<=mx;i++){
if(pos>=sit) ans+=dfs2(pos-1,sum+i,sit,flag&&i==mx);
else if(pos<sit) ans+=dfs2(pos-1,sum-i,sit,flag&&i==mx);
}
if(!flag) f[pos][sum]=ans;
return ans;
}
ll calc(ll x){
top=0;
ll ans=0;
while(x) q[++top]=x%k,x/=k;
cl(f),ans+=dfs1(top,0,1);
for(int i=2;i<=top;i++) cl(f),ans-=dfs2(top,0,i,1);
return ans;
}
int main(){
l=read(),r=read(),k=read();
cout<<calc(r)-calc(l-1)<<endl;
}