CF1816F Xor Counting - dp - 分治 -
题目链接:https://codeforces.com/contest/1816/problem/F
题解:
一道有趣的题。
- 首先发现 和 时结论是平凡的。 时结论显然,下面讨论一下 时:
首先可以构造 ,其中 和 同奇偶,显然此时异或值可以取到 的所有和 奇偶性相同的值。另一方面,一个重要观察是 的奇偶性和 相同,因此异或值至多取到所有和 奇偶性相同的值。因此这块可以 求出。 - 下面我们讨论一下 的情况。
设 表示 时的答案,考虑分治:
如果 为奇数,那么 一奇一偶,不失一般性设 分别为奇数 偶数,如果令 ,那么 ,因此我们还需要记一个 表示有多少种不同的异或值(因为这个 +1 是对于所有不同的异或值都要算的), 此时的转移也很简单。综上我们有 为奇数时 以及
如果 为偶数,那么 要么都是奇数,要么都是偶数,还是考虑 /2 分治,此时由于 奇数,所以没有 +1 的项,因此和上一种情况完全相同的推导我们有 以及 。
直接递推实现即可,复杂度 。
代码:
// by SkyRainWind
#include <bits/stdc++.h>
#define mpr make_pair
#define debug() cerr<<"Yoshino\n"
#define pii pair<int,int>
#define pb push_back
using namespace std;
typedef long long ll;
typedef long long LL;
const int inf = 1e9, INF = 0x3f3f3f3f, mod = 998244353;
map<ll,ll>f,g;
void solve(ll n){
if(n == 0){
f[n] = 0, g[n] = 1;
return ;
}
if(f.count(n))return ;
if(n%2 == 1){
solve(n/2);
(f[n] = 2ll*f[n/2]%mod + g[n/2])%=mod;
g[n] = g[n/2];
}else{
solve(n/2);solve(n/2-1);
f[n] = 2ll * (f[n/2] + f[n/2-1]) % mod;
g[n] = (g[n/2] + g[n/2-1]) % mod;
}
}
signed main(){
int te;scanf("%d",&te);
while(te --){
f.clear(), g.clear();
ll n,m;cin >> n >> m;
if(m == 1){
cout << n%mod << '\n';
}else if(m >= 3){
if(n%2 == 1)cout << (n+1)/2%mod*((n+1)/2%mod)%mod << '\n';
else cout << (1+n/2%mod)*(n/2%mod) % mod << '\n';
}else{
solve(n);
cout << f[n] << '\n';
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下