[题解]CF855E Salazar Slytherin's Locket
思路
毒瘤数位 DP 题。
首先,你可以用一个 vector
储存每一个数字出现的次数,然后用 map
记忆化。
然后可以得到如下 TLE #8 的代码。
因为 map
自带一只 所以,考虑将 map
优化掉。但是,现在每一种数字可能会出现很多次,所以要用 vector
维护出现次数,但这样必定需要用 map
一类的东西维护。
但是,本题只需要维护每一个数字出现次数的奇偶性,所以,你就可以用二进制来维护一下,这样就把 map
优化掉了。
然后可以得到如下 TLE #11 的代码。
因为 是一个很大的数,然而,我们在每一次记忆化搜索的时候都要 memset(dp,-1,sizeof(dp))
,所以时间复杂度直接降为 。(其中 为数字的长度)
但是,在对于同一个进制 时,每一次相同位置的 值是相同的,所以,直接再开一维表示进制即可。
Code
#include <bits/stdc++.h>
#define int long long
#define re register
using namespace std;
const int N = 110,M = 2010,K = 15;
int T,s,l,r;
int arr[N];
int dp[K][N][M];
inline int read(){
int r = 0,w = 1;
char c = getchar();
while (c < '0' || c > '9'){
if (c == '-') w = -1;
c = getchar();
}
while (c >= '0' && c <= '9'){
r = (r << 3) + (r << 1) + (c ^ 48);
c = getchar();
}
return r * w;
}
inline int dfs(int u,int st,bool z,bool lm){
if (!u) return (!st);
if (!z && !lm && ~dp[s][u][st]) return dp[s][u][st];
int res = 0,Max = s - 1;
if (lm) Max = arr[u];
for (re int i = 0;i <= Max;i++){
if (i || !z) st ^= (1ll << i);
res += dfs(u - 1,st,z && (!i),lm && (i == Max));
if (i || !z) st ^= (1ll << i);
}
if (!z && !lm) dp[s][u][st] = res;
return res;
}
inline int calc(int x){
int len = 0;
while (x){
arr[++len] = x % s;
x /= s;
}
return dfs(len,0,true,true);
}
signed main(){
memset(dp,-1,sizeof(dp));
T = read();
while (T--){
s = read();
l = read();
r = read();
printf("%lld\n",calc(r) - calc(l - 1));
}
return 0;
}
作者:WaterSun
出处:https://www.cnblogs.com/WaterSun/p/18263309
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效