【DP,位运算】Brave Seekers of Unicorns
传送门:https://codeforces.com/gym/102956
题目大意:
统计满足下列条件的数列的方案数:
- 非空
- 严格递增
- 任意连续三个元素的异或和不为
- 元素小于等于给定的
分析:
表示以 为尾的方案数。
考虑状态转移:
- 如果 只有一个元素,自然属于一种方案。
- 如果 的上一个数是
- 时,直接转移即可
- 否则,
写出更为一般化的公式就是:
,这里的 满足
我们记 (
是我乱起的)为二进制中 除了最高位为 其余全部清 所对应的数,例如:
注意到 与 必须位数相等(充分必要条件)。
因此,我们可以得到更为精确的 的范围
记 ,我们只需找到一个快速统计 的办法就好了。
举两个例子(二进制):
,对应的 为 (不一定是依次对应的)。
,
对应的 为 ,以及 (不一定是依次对应的)。
从中我们发现了规律:
记 ,然后每一次取 的 ,区间 都是满足的,我们依次统计就好了。
证明挺简单的,就留作习题吧。
我自己乱搞了一个求 的算法:
就是求 即可。
如果感觉不太好懂可以用下面的打表程序试试:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+6;
int highbit[N];
void init(){
for(int i=2;i<N;i++){
highbit[i]=highbit[i/2]+1;
}
for(int i=2;i<N;i++)
highbit[i]=1LL<<highbit[i];
highbit[1]=1;
}
void get(int x){
vector<int> v;
while(x) v.push_back(x%2), x>>=1;
reverse(v.begin(),v.end());
for(auto i:v) cout<<i;
cout<<' ';
}
int main(){
init();
int i; cin>>i;
for(int j=highbit[i];j<=i-1;j++)
get(j^i), puts("");
return 0;
}
原题代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+6;
const int mod=998244353;
long long f[N],s[N];
int highbit[N];
void init(){
for(int i=2;i<N;i++){
highbit[i]=highbit[i/2]+1;
}
for(int i=2;i<N;i++)
highbit[i]=1LL<<highbit[i];
highbit[1]=1;
}
int main(){
init();
int n; cin>>n;
cerr<<highbit[N-1];
for(int i=1;i<=n;i++){
auto &v=f[i];
v=1;
v=(v+s[i-1])%mod;
int t=i;
t-=highbit[t];
while(t){
int x=highbit[t];
v=(v-(s[(x<<1)-1]-s[x-1])+mod)%mod;
t-=x;
}
s[i]=(s[i-1]+v)%mod;
}
cout<<s[n]<<endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】