题解:CF2086E Zebra-like Numbers
dayz_break404 · · 题解
一道不那么板的数位 DP,感觉思路很清奇。
显然斑马数不超过
考虑这个进制,由于斑马值是最小的系数和,从高位到低位贪心一定是最优的。并且由于有
那么 DP 状态为
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
inline ll read(){
ll x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x*f;
}
bool mbs;
ll t,l,r,k,num[32],val[32],dp[32][100][2][2];
ll dfs(int pos,int sum,int lim1,int lim2){
if(!pos) return sum==k;
if(dp[pos][sum][lim1][lim2]!=-1) return dp[pos][sum][lim1][lim2];
int up=4;ll res=0;
if(lim2) up=0;
else if(lim1) up=val[pos];
for(int i=0;i<=up;i++) res+=dfs(pos-1,sum+i,lim1&&i==val[pos],lim2||i==4);
return dp[pos][sum][lim1][lim2]=res;
}
inline ll get_val(ll x){
for(int i=30;i>=1;i--) val[i]=(x/num[i]),x-=(x/num[i])*num[i];
memset(dp,-1,sizeof(dp));
return dfs(30,0,1,0);
}
inline void solve(){
l=read(),r=read(),k=read();
printf("%lld\n",get_val(r)-get_val(l-1));
}
bool mbt;
int main(){
// cout<<(&mbs-&mbt)/1024.0/1024.0<<endl;
num[1]=1;
for(int i=2;i<=30;i++) num[i]=num[i-1]*4+1;
t=read();
while(t--) solve();
return 0;
}