【学习笔记】[ZJOI2019] 开关

之前没认真学 F W T FWT FWT可惜了😅

首先要做过这道题 [AGC034F] RNG and XOR

考虑 I F W T IFWT IFWT算法的本质🤔

之前我们注意到将 k k k的顺序调换并不会影响结果,也就是说只要做一遍 F W T FWT FWT,然后再除以 2 n 2^n 2n就是答案。

考虑优化🤔,发现从 P ^ i \widehat P_i P i变成 P ^ i + 2 j \widehat P_{i+2^j} P i+2j相当于整体偏移一个定值,可以用背包记录!最后再记录一下奇偶性就好了!

复杂度 O ( n ∑ p ) O(n\sum p) O(n∑p)。

remark \text{remark} remark 感觉这部分算法的性质蛮多的!

cpp 复制代码
#include<bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
#define db double
using namespace std;
const int mod=998244353;
const int N=1e5+5;
int n,a[105],p[105],s;
ll now[N][2],nxt[N][2],res;
void add(ll &x,ll y){
    x=(x+y)%mod;
}
ll fpow(ll x,ll y=mod-2){
    ll z(1);
    for(;y;y>>=1){
        if(y&1)z=z*x%mod;
        x=x*x%mod;
    }return z;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin>>n;for(int i=0;i<n;i++)cin>>a[i];
    for(int i=0;i<n;i++)cin>>p[i],s+=p[i];
    now[2*s][0]=1;
    for(int i=0;i<n;i++){
        memset(nxt,0,sizeof nxt);
        for(int j=0;j<=2*s;j++){
            for(int k=0;k<2;k++){
                if(now[j][k]){
                    add(nxt[j][k],now[j][k]);
                    add(nxt[j-2*p[i]][k^a[i]],now[j][k]);
                }
            }
        }
        memcpy(now,nxt,sizeof nxt);
    }ll mul=fpow(s);
    for(int i=0;i<=2*s;i++){
        if(now[i][1]){
            add(res,2*fpow(1-(i-s)*mul%mod)*now[i][1]%mod);
        }
    }
    cout<<(res+mod)%mod;
}
相关推荐
chudonghao33 分钟前
[UE学习笔记][基于源码] 理解 Gameplay
c++·笔记·学习·ue5
Nan_Shu_6141 小时前
学习:Cesium (4)
前端·学习
炽烈小老头1 小时前
【 每天学习一点算法 2026/03/25】在排序数组中查找元素的第一个和最后一个位置
学习·算法
movigo7_dou2 小时前
关于光与重建方法的学习3.25
学习
AI-Ming2 小时前
程序员转行学习AI大模型:位置编码
人工智能·神经网络·学习
左左右右左右摇晃2 小时前
数据结构——数组
数据结构·笔记·算法
nainaire2 小时前
速通LeetCode hot100——(1~9 哈希,双指针,滑动窗口)
c++·笔记·算法·leetcode
hmbbcsm2 小时前
动手学习深度学习学习笔记(一)
笔记·学习
春水碧于天,画船听雨眠2 小时前
jQuery学习笔记
笔记·学习·jquery
一个天蝎座 白勺 程序猿3 小时前
Oracle替换工程实践深度解析:从迁移挑战到金仓“零改造”实践
数据库·学习·oracle·kingbasees