CF855E题解
本文同步更新于洛谷博客
题目描述
求 中所有满足 中各个数码均出现偶数次的 的个数。
题解
由于最多只有 个不同的数字,因此我们可以对每个数字出现的个数进行二进制状态压缩, 表示出现偶数次, 表示出现奇数次。下面说一下状态如何转移,因为我们每次要将某一位上的 变为 , 变为 ,因此我们将 与 按位异或即可( 表示填入的数)。
接下来就是的数位 dp 了,我们传四个参数 进入 dfs,分别表示枚举到第 位,当前每个数字出现次数的状态,是否为前导 ,以及这一位填的数有没有限制,用 数组记忆化即可。
注意
- 我们不用计算 中 的个数,因为当且仅当 时所有数码出现的次数均为偶数
- 只有将 数组添加一维表示当前的数是 进制才能只初始化一遍,我第一次就是因为这个 WA 了。
Code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int q,b,len,a[65];
ll l,r,f[11][65][1024];
ll dfs(int k,int sta,int p,int q)
{
if(!k)
return !sta;
if(!p&&!q&&f[b][k][sta]!=-1)
return f[b][k][sta];
int y=q?a[k]:(b-1);
ll res=0;
for(int i=0;i<=y;i++)
res+=dfs(k-1,(p&&!i)?0:(sta^(1<<i)),p&&!i,q&&(i==y));
if(!p&&!q)
f[b][k][sta]=res;
return res;
}
ll divide(ll x)
{
len=0;
while(x)
{
a[++len]=x%b;
x/=b;
}
return dfs(len,0,1,1);
}
int main()
{
memset(f,-1,sizeof(f));
scanf("%d",&q);
while(q--)
{
scanf("%d%lld%lld",&b,&l,&r);
printf("%lld\n",divide(r)-divide(l-1));
}
return 0;
}
本文作者:Ginger_he
本文链接:https://www.cnblogs.com/Gingerhe/p/15844504.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步