当前位置:首页 > 技术 > 正文内容

表达式求解中的模运算与深度优先搜索优化

访客 技术 2026年6月24日 1

在解决涉及多个变量的代数表达式奇偶性判断问题时,常可通过模 2 运算将复杂计算简化为二进制位分析。例如,对于表达式 (B + E + S + S + I + E)(G + O + E + S)(M + O + O),其结果是否为偶数仅取决于各变量取值的奇偶性。

由于奇偶性在加法和乘法下具有封闭性:

  • 偶 + 奇 = 奇
  • 偶 + 偶 = 偶
  • 奇 × 奇 = 奇
  • 偶 × 奇 = 偶

因此,可将原式等价化简为:(B + I)、(G + O + E + S)、M 中至少有一个为偶数,则整体结果为偶数。这使得原本需枚举 20⁷ 种组合的问题,转化为只需考虑每个变量奇偶性的 2⁷ 种情况,极大降低复杂度。

通过深度优先搜索(DFS)遍历所有奇偶组合,并结合预处理各变量奇数与偶数的出现次数,可高效统计满足条件的赋值方案总数。

#include <iostream>
#include <map>
#include <vector>
using namespace std;

long long ans;
map<char, int> oddCount, evenCount;
vector<char> vars = {'B', 'E', 'S', 'I', 'G', 'O', 'M'};
map<char, int> choice;

void dfs(int idx, long long currentWays) {
    if (idx == vars.size()) {
        int sum1 = choice['B'] + choice['I'];
        int sum2 = choice['G'] + choice['O'] + choice['E'] + choice['S'];
        int sum3 = choice['M'];
        if ((sum1 % 2 == 0) || (sum2 % 2 == 0) || (sum3 % 2 == 0)) {
            ans += currentWays;
        }
        return;
    }

    char var = vars[idx];
    // 尝试奇数
    choice[var] = 1;
    dfs(idx + 1, currentWays * oddCount[var]);

    // 尝试偶数
    choice[var] = 0;
    dfs(idx + 1, currentWays * evenCount[var]);
}

int main() {
    int n;
    cin >> n;
    while (n--) {
        char ch;
        int val;
        cin >> ch >> val;
        if (val % 2) oddCount[ch]++;
        else evenCount[ch]++;
    }

    dfs(0, 1);
    cout << ans << endl;
    return 0;
}

对于线性不定方程 $ ax + by = n $ 求非负整数解的问题,因变量范围有限(≤1000),可直接枚举 $ x $ 从 0 到 $ \lfloor n/a \rfloor $,验证 $ (n - a x) $ 是否能被 $ b $ 整除且商非负。

int main() {
    int a, b, n;
    cin >> a >> b >> n;
    for (int x = 0; x <= n / a; ++x) {
        int remainder = n - a * x;
        if (remainder >= 0 && remainder % b == 0) {
            int y = remainder / b;
            cout << "Solution: x=" << x << ", y=" << y << endl;
            return 0;
        }
    }
    cout << "No solution" << endl;
    return 0;
}

在四元表达式最小值问题中,给定四个数及三个操作符(+ 或 *),要求按顺序依次合并相邻两项,目标是使最终结果最小。由于操作顺序固定,不能交换操作符,但可枚举合并顺序。使用 DFS 枚举每一步的合并对,递归构造新数组并更新最小值。

注意:数值可能溢出,应使用 long long;零的存在可能导致乘积为零,影响剪枝策略。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

typedef long long ll;
ll minResult = 1e18;

void dfs(vector<ll> nums, int opIdx) {
    if (nums.size() == 1) {
        minResult = min(minResult, nums[0]);
        return;
    }

    vector<ll> nextNums;
    for (int i = 0; i < nums.size(); ++i) {
        for (int j = i + 1; j < nums.size(); ++j) {
            nextNums.clear();
            for (int k = 0; k < nums.size(); ++k) {
                if (k != i && k != j) nextNums.push_back(nums[k]);
            }
            if (opIdx == 0) nextNums.push_back(nums[i] + nums[j]);
            else if (opIdx == 1) nextNums.push_back(nums[i] * nums[j]);
            dfs(nextNums, opIdx + 1);
        }
    }
}

int main() {
    vector<ll> values(4);
    for (int i = 0; i < 4; ++i) cin >> values[i];

    string ops;
    cin >> ops;

    dfs(values, 0);
    cout << minResult << endl;
    return 0;
}

四平方和问题要求找到一组非负整数 $ a \leq b \leq c \leq d $ 使得 $ a^2 + b^2 + c^2 + d^2 = n $,并保证字典序最小。采用分治思想:先预处理所有 $ c^2 + d^2 $ 的组合,存入哈希表;再枚举 $ a^2 + b^2 $,检查剩余部分是否存在。

#include
#include
using namespace std;

const int MAXN = 1e4 + 5;
int C[MAXN], D[MAXN];

int main() {
int n;
cin >> n;
memset(C, -1, sizeof C);

for (int c = 0; c * c <= n; ++c) {
for (int d = c; d * d + c * c <= n; ++d) {
int sum = c * c + d * d;
if (C[sum] == -1) {
C[sum] = c;
D[sum] = d;
}
}
}

for (int a = 0; a * a <= n; ++a) {
for (int b = a; b * b + a * a <= n; ++b) {
int rem = n - a * a - b * b;
if (C[rem] != -1) {
cout << a << " " << b << " " << C[rem] << " " << D[rem] << endl;
return 0;
}
}
}
return 0;
}
标签: 模运算

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。