灵茶八题 题目解析+核心代码

子数组+w+

  1. 由于仅存在加法,即满足交换律和结合律,故可考虑累加单个元素的总贡献
  2. 对当前元素g[i],包含该元素的子数组数为(i + 1) * (n - i + 1),则该元素的总贡献为(i + 1) * (n - i) * g[i],枚举所有元素累加即可
    • i起始为1
void solve(){
    int n;
    cin >> n;

    ll res = 0;
    for(int i = 1; i <= n; i++){
        int x;
        cin >> x;
        res += 1ll * i * (n - i + 1) * x;
    }

    cout << res << '\n';
}

子数组^w^

类似考虑单个元素总贡献,当元素g[i]的出现次数(i + 1) * (n - i)为奇数时总贡献为g[i],否则为0,计算异或和即可

void solve(){
    int n;
    cin >> n;

    ll res = 0;
    for(int i = 1; i <= n; i++){
        int x;
        cin >> x;

        x = (((n - i + 1) * i) & 1) * x;
        res ^= x;
    }

    cout << res << '\n';
}

子数组^w+

  1. 考虑异或前缀和sx[i],对任意子数组的异或和可表示为sx[r] ^ sx[l - 1]
  2. 考虑二进制拆位,即枚举累加每个二进制位的贡献
  3. 对当前位k,相当于在前缀和数组中选取两个元素,使sx[r] ^ sx[l - 1]中该位为1,即sx[r]sx[l - 1]必须恰好一个1一个0,此时贡献为1 << k
  4. 枚举统计前缀和数组中当前位下为1的元素个数cnt,则为0的个数为(n + 1 - cnt),故存在贡献的子数组的总贡献为cnt * (n + 1 - cnt) * (1 << k)
void solve(){
    int n;
    cin >> n;

    ve<int> sx(n + 1);
    for(int i = 1; i <= n; i++){
        cin >> sx[i];
        sx[i] ^= sx[i - 1];
    }

    ll res = 0;
    for(int k = 0; k < 22; k++){
        int cnt = 0;
        for(int i = 0; i <= n; i++) cnt += sx[i] >> k & 1;
        res += 1ll * cnt * (n + 1 - cnt) * (1 << k);
    }

    cout << res << '\n';
}

子数组+w^

  1. 考虑前缀和 s [ i ] s[i] s[i],对任意子数组和可表示为 s [ r ] − s [ l − 1 ] s[r] - s[l - 1] s[r]s[l1]

  2. 考虑二进制拆位,即枚举累加每个二进制位的贡献

  3. 对当前 k k k位,需要获取所有子数组和该位为1的数量,若为奇数则贡献为 2 k 2^k 2k,否则为0

  4. 问题转换为求指定位下所有子数组和该位为1的数量

  5. 只考虑低位到 k k k位,令所有 s [ i ] s[i] s[i] 2 k + 1 2^{k + 1} 2k+1取模,从而将 s [ r ] − s [ l − 1 ] s[r] - s[l - 1] s[r]s[l1]的结果及其 s [ r ] s[r] s[r] s [ l − 1 ] s[l - 1] s[l1]压缩到一定连续范围内

  6. k = 2 k = 2 k=2时, s [ r ] − s [ l − 1 ] s[r] - s[l - 1] s[r]s[l1]产生 k k k位为1的结果范围为[100, 111],考虑减法操作中高位的影响,如1000 - 1 = 111的结果满足条件,故当 s [ r ] ≥ 2 k + 1 s[r]≥2^{k + 1} s[r]2k+1时,在 k + 1 k+1 k+1位补1,此时结果范围为 [ 100 , 111 ] ∪ [ 1100 , 1111 ] [100,111]∪[1100,1111] [100,111][1100,1111],则 s [ l − 1 ] s[l - 1] s[l1]的范围为

    [ s [ r ] − 111 , s [ r ] − 100 ] ∪ [ s [ r ] − 1111 , s [ r ] − 1100 ] [s[r]-111, s[r]-100]∪[s[r]-1111,s[r]-1100] [s[r]111,s[r]100][s[r]1111,s[r]1100]

  7. 枚举所有 s [ r ] s[r] s[r],对当前 s [ r ] s[r] s[r]获取 [ 1 , r − 1 ] [1, r - 1] [1,r1]中在区间内的 s [ l − 1 ] s[l - 1] s[l1]的个数进行累加,最后得到当前位下所有子数组和该位为1的数量

  8. 由于 [ 1 , r − 1 ] [1, r-1] [1,r1]是动态区间,故使用树状数组维护即可

const int N = 2e7 + 10;

ve<int> tr(N);

int lowbit(int x){
    return x & -x;
}

void add(int idx, int val){
    idx++;
    for(int i = idx; i < N; i += lowbit(i)) tr[i] += val;
}

int sum(int x){
    x++;
    int ans = 0;
    while(x > 0){
        ans += tr[x];
        x -= lowbit(x);
    }
    return ans;
}

void solve(){
    int n;
    cin >> n;

    ve<int> s(n + 1);
    for(int i = 1; i <= n; i++){
        cin >> s[i];
        s[i] += s[i - 1];
    }

    int res = 0;
    for(int k = 0; (1 << k) <= s[n]; k++){
        add(0, 1);

        int cnt = 0;
        for(int i = 1; i <= n; i++){
            int ts = s[i] & ((1 << (k + 1)) - 1);
            if(s[i] >= 1 << (k + 1)) ts |= 1 << (k + 1);

            int r = ts - (1 << k), l = ts - (1 << (k + 1)) + 1;
            cnt += sum(r) - sum(l - 1);
            l -= 1 << (k + 1), r -= 1 << (k + 1);
            cnt += sum(r) - sum(l - 1);

            add(s[i] & ((1 << (k + 1)) - 1), 1);
        }

        if(cnt & 1) res |= 1 << k;

        fill(all(tr), 0);
    }

    cout << res << '\n';
}

子序列+w+

  1. 由于仅存在加法,即满足交换律和结合律,故可考虑累加单个元素的总贡献
  2. 对于元素g[i],包含该元素的子序列总数为 2 n − 1 2^{n-1} 2n1,即总贡献为 2 n − 1 ∗ g [ i ] 2^{n-1}*g[i] 2n1g[i]
  3. 所有元素总贡献为 2 n − 1 ∗ s u m 2^{n-1}*sum 2n1sum
void solve(){
    int n;
    cin >> n;

    ll res = 0;
    for(int i = 0; i < n; i++){
        int x;
        cin >> x;
        res += x;
    }

    for(int i = 0; i < n - 1; i++) res = 2 * res % mod;

    cout << res << '\n';
}

子序列^w^

  1. 类似可考虑累加异或单个元素的总贡献
  2. 当且仅当n = 1存在贡献g[0],否则 2 n − 1 2^{n-1} 2n1为偶数,总贡献为0
void solve(){
    int n;
    cin >> n;

    ve<int> g(n);
    for(int i = 0; i < n; i++) cin >> g[i];

    if(n == 1) cout << g[0] << '\n';
    else cout << 0 << '\n';
}

子序列^w+

  1. 考虑二进制拆位,即枚举累加每个二进制位的贡献
  2. 对于当前位k,若所有元素都为0,则总贡献为0
  3. 若存在元素为1,设数量为c,可用数学归纳法证明从c个数中选偶数个数和奇数个数的方案数都为 2 c − 1 2^{c-1} 2c1,再算上0可得异或和为0和为1的子序列数都为 2 n − 1 2^{n-1} 2n1
  4. 则此时该位总贡献为 2 n − 1 ∗ 2 k 2^{n-1}*2^{k} 2n12k
void solve(){
    int n;
    cin >> n;

    ve<int> g(n);
    for(int i = 0; i < n; i++) cin >> g[i];

    ll res = 0;
    for(int k = 0; k < 30; k++){
        bool ok = false;
        for(int i = 0; i < n; i++){
            if(g[i] >> k & 1){
                ok = true;
                break;
            }
        }

        if(ok) res += 1 << k;
    }

    for(int i = 0; i < n - 1; i++) res = 2 * res % mod;

    cout << res << '\n';
}

子序列+w^

  1. 考虑枚举累加每个子序列和的可能值的贡献
  2. 对当前序列数和sum,得到该和的方案数为奇数时贡献为sum,否则为0
  3. 考虑使用01背包推导序列数和的方案数的奇偶性
void solve(){
    int n;
    cin >> n;

    int m = 1 << 16;
    ve<int> dp(m + 1);
    dp[0] = 1;

    for(int i = 0; i < n; i++){
        int v;
        cin >> v;

        for(int j = m; j >= v; j--){
            dp[j] = dp[j] ^ dp[j - v];
        }
    }

    int res = 0;
    for(int i = 0; i <= m; i++){
        if(dp[i]){
            res ^= i;
        }
    }

    cout << res << '\n';
}
  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
一、资源详解 实验报告:通过实际操作与数据记录,让您深入理解计算机内部的工作原理。每份实验报告都详细记录了实验步骤、结果及分析,助您巩固知识点。 学习笔记:由资深学者精心整理的学习笔记,重点突出,为您梳理课程脉络,把握核心内容。 复习资料与试卷:涵盖了各类复习资料和历年试卷,助您备战考试,查漏补缺,提高应试能力。 作业答案:提供完整的作业答案及解析,让您在完成课后作业时更有信心,确保理解每一个知识点。 一二、计算机组成原理:从基础到进阶,全面突破的必备资源 在信息爆炸的时代,计算机组成原理作为计算机科学的核心课程,显得尤为重要。为了帮助广大学子更好地掌握这一关键领域,我们特地整理了这一系列与计算机组成原理相关的资源,助力您的学术旅程。 三、适用场景广泛 无论是期末考试冲刺、计算机组成原理实验报告作业、还是复习题、试题、考研资料等需求,这些资源都能满足您的要求。全面覆盖理论要点与实践操作,让您在学习和备考过程中游刃有余。 四、使用建议 系统学习:建议按照章节顺序进行系统学习,结合实验报告进行实践操作,以加深理解。 备考策略:利用复习资料与试卷资源,制定有效的备考计划,提高考试通过率。 持续反馈与改进:根据作业答案进行自我评估,找出薄弱环节,及时调整学习策略。 五、版权与安全提示 尊重知识产权:在使用这些资源时,请尊重原作者的权益,遵守版权法规。 安全使用:确保在使用过程中不侵犯他人权益,避免任何形式的学术不端行为。 感谢您选择我们的计算机组成原理资源库!让我们一起深入探索计算机的奥秘,用知识武装自己,开启精彩的学术之旅!
**JAVA+SQL离散数学题库管理系统** 本资源提供了一个基于Java和SQL的离散数学题库管理系统的完整解决方案。该系统旨在帮助教育者和学生更有效地管理和学习离散数学题目。它包括强大的功能,如题目的增删改查、难度分级、知识点分类以及考试试卷的生成与管理。 **核心功能特点:** 1. **题库管理**:支持离散数学题目的批量导入、导出和存储,方便教师或管理员进行题目的更新和整理。 2. **题目查询与筛选**:用户可以根据关键字、难度、知识点等多个条件进行题目的精确查询和筛选。 3. **试卷生成**:系统可根据用户选择的难度、题型和知识点自动生成试卷,支持自定义试卷设置。 4. **在线学习与测试**:提供用户在线答题和测试的功能,系统自动评分并给出答案解析,帮助用户及时了解自己的学习情况。 5. **用户权限管理**:系统支持多角色用户管理,不同角色拥有不同的操作权限,确保数据的安全性和系统的稳定性。 6. **数据备份与恢复**:定期对题库数据进行备份,以防数据丢失,同时提供数据恢复功能,确保系统的持续运行。 **技术架构:** 后端采用Java语言开发,利用Spring Boot框架实现系统的快速开发和部署。前端使用HTML、CSS和JavaScript等Web技术构建用户界面,提供良好的用户体验。数据库采用SQL Server或MySQL等关系型数据库,确保数据的稳定存储和高效检索。 **二次开发定制:** 本系统具有良好的扩展性和可定制性,开发者可以根据实际需求进行二次开发,如添加新的功能模块、优化系统性能等。同时,系统提供详细的文档和示例代码,帮助开发者快速上手和定制开发。 **适用场景:** 本系统适用于高校、培训机构等离散数学教学环境,帮助教师和学生更好地管理离散数学题目,提高教学效果和学习效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

西西努力变强

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值