SP10606 题解
题目大意:
给你两个数
思路:
看到记录每一数位出现几次,就是直接告诉你这是数位dp。至于如何记录每个数出现过多少次,我们可以选择状压,用一个二进制数
由于每个数位要么出现奇数次,要么出现偶数次,我们可以用
而
这样,我们只要开个
最终 AC:90ms,201MB。
代码:
可能非常压行。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define TP template<typename T>
#define TP_ template<typename T,typename ... T_>
TP void read(T &x)
{
x=0;int f=0;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())ch=='-'&&(f=1);
for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<1)+(x<<3)+(ch^48);
f&&(x=-x);
}
TP_ void read(T &x,T_&...y){read(x);read(y...);}
TP void write(T x){x<0&&(putchar('-'),x=-x);static int sta[35];int top=0;do{sta[++top]=x%10;x/=10;}while(x);while(top){putchar(sta[top--]^48);}}
TP void writeln(const T x){write(x);puts("");}
TP void writesp(const T x){write(x);putchar(32);}
TP_ void writeln(const T x,T_ ...y){writesp(x);writeln(y...);}
using LL=unsigned long long;
constexpr int N=25;
constexpr int B=10;
LL dp[N][1<<B][1<<B],a[N],len;
LL dfs(int pos,bool lead,int sta,bool limit,int cnt)
{
if(!pos)return sta==cnt;
if(!limit&&!lead&&~dp[pos][sta][cnt])return dp[pos][sta][cnt];
int res=0,up=limit?a[pos]:B-1;
for(int i=0;i<=up;i++)
res+=dfs(pos-1,lead&&!i,(lead&&!i)?0:(sta^(1<<i)),limit&&i==up,(lead&&!i)?0:((!(i&1))?(cnt|(1<<i)):cnt));
return limit?res:(lead?res:dp[pos][sta][cnt]=res);
}
LL calc(LL x)
{
len=0;
while(x)a[++len]=x%B,x/=B;
return dfs(len,1,0,1,0);
}
int main()
{
int T;read(T);
memset(dp,-1,sizeof(dp));
while(T--)
{
LL l,r;
read(l,r);
writeln(calc(r)-calc(l-1));
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现