专栏文章
题解:CF2086E Zebra-like Numbers
CF2086E题解参与者 3已保存评论 7
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 7 条
- 当前快照
- 1 份
- 快照标识符
- @mipn8snb
- 此快照首次捕获于
- 2025/12/03 14:46 3 个月前
- 此快照最后确认于
- 2025/12/03 14:46 3 个月前
一道不那么板的数位 DP,感觉思路很清奇。
显然斑马数不超过 个,记斑马数为 ,那么答案是一个多项式的形式,考虑将其转化为进制的形式。
考虑这个进制,由于斑马值是最小的系数和,从高位到低位贪心一定是最优的。并且由于有 ,所以每一位上的数值都不大于 ,并且如果有一位为 ,则它的更低位一定是 。
那么 DP 状态为 ,表示当前 位,数位和为 ,是否达到数值限制,是否出现了 ,转移即可。
代码:
CPP#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;
}
相关推荐
评论
共 7 条评论,欢迎与作者交流。
正在加载评论...