Codeforces Round 1004 (Div. 1) C. Bitwise Slides

Codeforces Round 1004 (Div. 1) C. Bitwise Slides

题意:

  • 给你一个数组,三个整数P,Q,R​

  • 每一个操作使得P,Q,R三个数中的某个数异或s[i]

  • 每一步操作后需要保证三个数中至少两个数相同,问合法操作的种类数

思路:

首先考虑二维 d p dp dp,假设当前三个数为上一次操作后三个数为 i,i,j,那么 d p i , j dp_{i,j} dpi,j代表上次操作产生i,i,j​的种类数

假设当前的数为s[i]​,那么那么有以下转移方程:
d p 0 0 × 3 → d p 0 s \[ i ] d p i j → d p i j ⊕ s \[ i ] if j ⊕ s i ≠ i d p i j × 2 → d p j i if j ⊕ s i = i \begin{aligned} dp00 \times 3 &\rightarrow dp0s\[i] \\ dpij &\rightarrow dpij \\oplus s\[i] \quad \text{if} \ j \oplus si \neq i \\ dpij \times 2 &\rightarrow dpji \quad \text{if} \ j \oplus si = i \end{aligned} dp00×3dpijdpij×2→dp0s\[i]→dpij⊕s\[i]if j⊕si=i→dpjiif j⊕si=i

我们发现,只记录 y = i ⊕ j y=i \oplus j y=i⊕j可以使得
d p ′ y = ∑ i = j ⊕ y d p i j dp^{'}y=\sum _{i=j \oplus y} dpij dp′y=i=j⊕y∑dpij

这样,转移方程变为:
d p 0 × 3 → d p s \[ i ] d p s \[ i ] → 2 × d p s \[ i ] d p i → d p i ⊕ s \[ i ] for all i \begin{aligned} dp0 \times 3 &\rightarrow dps\[i] \\ dps\[i] &\rightarrow 2 \times dps\[i] \\ dpi &\rightarrow dpi \\oplus s\[i] \quad \text{for all} \ i \end{aligned} dp0×3dps\[i]dpi→dps\[i]→2×dps\[i]→dpi⊕s\[i]for all i

由此我们可以写出以下代码:

cpp 复制代码
		map<int, int> dp;
        dp[s[0]] = 3;
        for (int i = 1; i < n; i++)
        {
            map<int, int> tem;
            for (auto j : dp)
            {
                if (j.first == s[i])
                    tem[s[i]] = (tem[s[i]] + (dp[j.first] * 2) % mod) % mod;
                if (j.first != 0)
                    tem[j.first ^ s[i]] = (tem[j.first ^ s[i]] + dp[j.first]) % mod;
                else
                    tem[j.first ^ s[i]] = (tem[j.first ^ s[i]] + (dp[j.first] * 3) % mod) % mod;
            }
            dp = tem;
        }

我们发现设置一个tag能将所有 d p x dpx dpx 整体变为 d p x ⊕ s \[ i ] dpx \\oplus s\[i] dpx⊕s\[i],于是有了以下优化

cpp 复制代码
		map<int, int> dp;
        dp[s[0]] = 3;
        for (int i = 1; i < n; i++)
            dp[now] = (dp[now] * 3) % mod, dp[now] = (dp[now] + (dp[now ^ s[i]] * 2) % mod) % mod, now ^= s[i];

从左到右枚举所有数后 ,答案为 ∑ d p i \sum dpi ∑dpi

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
#define int long long int
#define Paddi ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
const int mod = 1e9 + 7;
signed main()
{
    Paddi;
    int T;
    cin >> T;
    while (T--)
    {
        int n;
        cin >> n;
        vector<int> s(n);
        for (int i = 0; i < n; i++)
            cin >> s[i];
        int ans = 0;
        int now = 0;
        map<int, int> dp;
        dp[s[0]] = 3;
        for (int i = 1; i < n; i++)
            dp[now] = (dp[now] * 3) % mod, dp[now] = (dp[now] + (dp[now ^ s[i]] * 2) % mod) % mod, now ^= s[i];
        for (auto i : dp)
            ans = (ans + i.second) % mod;
        cout << ans % mod << endl;
    }
    return 0;
}
相关推荐
HPtiger5 小时前
数据结构——选择排序
数据结构·算法·排序算法
康实训5 小时前
老年评估仿真实训平台架构设计与老年人能力评估实训室教学落地实践
大数据·人工智能·算法·实训室·实训室建设
DongQiShanRen6 小时前
六根硬件映射(四):归属澄清、两处不一致与卷十一总表
开发语言·人工智能·算法·rust·哈希算法·集成学习
CCblandy6 小时前
雪花 ID 四个边界实测:时钟回拨重号 500 个,前端 JSON.parse 直接丢精度
后端·python·算法·性能优化·架构
丑梨数据6 小时前
信创环境里跑文档工具:格式兼容与本地合规的几个坑
数据结构·人工智能·算法·决策树·排序算法
把我格子衫拿来6 小时前
VTK 9.5 与 Qt 6 联合开发:从嵌入三维窗口到可维护的桌面架构
c++·python·qt·vtk·三维可视化
无忧.芙桃7 小时前
C++语言原理与实践(十六):多态机制讲解
开发语言·c++·多态
erzong2318 小时前
Linux操作系统:线程概念与控制
linux·算法
wuminyu8 小时前
JMM学习总结:深入理解happens-before关系
java·linux·c语言·jvm·c++
Nil2088 小时前
leetcode 5最长回文子串
算法·leetcode·职场和发展