C. Brave Seekers of Unicorns 题解(dp)

题目链接

题目大意

要你构造一个严格单调递增的数组$ 1\leq a[i] \leq n, 1\leq n \leq 1e6$

使得不存在任意三个数的异或和为0

即构造的数组不存在\(a[i]\bigoplus a[i+1]\bigoplus a[i+2]=0\)

题目思路

很明显是一个dp

\(dp[i]\)表示结尾元素为\(i\)的值的方案数

那么显然\(dp[i]=\sum_{j=1}^{j=r-1}dp[j]-dp[i\bigoplus j](i\bigoplus j<j)\)

主要就是要找到\(i\bigoplus j<j\)的情况

下面说结论

对于二进制下的 \(i\) ,如果第 \(x\) 位为 1,那么 \(2^x\)\(2^{x+1}-1\) 之间的数都是(除了最高位的1除外)
其实就是\(i\bigoplus j\)的最高位必定是必定是x有的二进制1,而且不能是最高位

这个其实可以手动模拟出来

代码

#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
typedef long long ll;
typedef pair<double,int> pdi;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int maxn=1e6+5,mod=998244353;
int n;
ll dp[maxn];
ll pre[maxn];
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        dp[i]=pre[i-1]+1;
        for(int j=0;j<=30;j++){
            if(i&(1<<j)&&i>=(1<<(j+1))){
                dp[i]-=pre[(1<<(j+1))-1]-pre[(1<<j)-1];
                dp[i]=(dp[i]%mod+mod)%mod;
            }
        }
        pre[i]=((pre[i-1]+dp[i])%mod+mod)%mod;
    }
    printf("%lld\n",pre[n]);
    return 0;
}

posted @ 2021-03-11 10:07  hunxuewangzi  阅读(161)  评论(0编辑  收藏  举报