首页 > 其他分享 >小红的数组回文值

小红的数组回文值

时间:2024-09-09 11:48:59浏览次数:4  
标签:limits cdot sum 元素 小红 数组 回文

小红的数组回文值

题目描述

小红定义一个数组的回文值是:修改最少数量的元素值得该数组回文,这个次数即数组的回文值。

例如,${3,2,4,3}$ 的回文值是 $1$,只需要将第二个元素修改为 $4$ 即可。

现在小红拿到了一个数组,她希望你求出所有子序列的回文值之和。你能帮帮她吗?

定义子序列为从数组中从左到右取出若干个元素(可以不取、可以全取、可以不连续)形成的数组。

输入描述:

第一行输入一个整数 $n(1 \leq n \leq 2000)$ 代表数组中的元素数量。

第二行输入 $n$ 个整数 $a_1, a_2, \ldots, a_n$ $(1 \leq a_i  \leq 10^9)$ 代表数组元素。

输出描述:

在一行上输出一个整数,代表所有子序列的回文值之和。由于答案可能很大,请将答案对 $(10^9 +7)$ 取模后输出。

示例1

输入

3
1 2 3

输出

4

说明

${1,2}$、${1,3}$、${2,3}$ 和 ${1,2,3}$ 的回文值都是 $1$。其余子序列的回文值均为 $0$。

示例2

输入

4
999 999 999 999

输出

0

 

解题思路

  比赛的时候不知道范德蒙德卷积,只能写暴力骗点分了。

  对于这种计数类问题可以先考虑贡献法。对于任意两个满足 $i < j$ 且 $a_i \ne a_j$ 的元素,显然在以 $a_i$ 和 $a_j$ 为对称元素的子序列中,因为 $a_i \ne a_j$ 所以会产生 $1$ 的贡献,因此 $a_i$ 和 $a_j$ 对答案的贡献就是满足这样要求的子序列的数量。

  先假设 $a_i$ 和 $a_j$ 在子序列中就是对称的元素,首先对于 $a_{i+1} \sim a_{j-1}$ 中的元素可以任意选择,不会改变 $a_i$ 和 $a_j$ 的对称性,有 $2^{j-i-1}$ 种方案。然后考虑左边 $a_{1} \sim a_{i-1}$ 和右边 $a_{j+1} \sim a_{n}$ 的选择,显然两边应该选择同等数量的元素,那么可选的方案数量为 $\sum\limits_{k=0}^{\min\{i-1, n-j\}}{C_{i-1}^{k} \cdot C_{n-j}^{k}}$。因此以 $a_i$ 和 $a_j$ 为对称元素的子序列的数量就是 $2^{j-i-1} \cdot \sum\limits_{k=0}^{\min\{i-1, n-j\}}{C_{i-1}^{k} \cdot C_{n-j}^{k}}$。

  最后总的答案就是$$\sum\limits_{i=1}^{n}{\sum\limits_{j=i+1}^{n}{[a_i \ne a_j] \left( 2^{j-i-1} \cdot \sum\limits_{k=0}^{\min\{i-1, j-n\}}{C_{i-1}^{k} \cdot C_{j-n}^{k}} \right)}}$$

  如果直接暴力计算 $\sum\limits_{k=0}^{\min\{i-1, n-j\}}{C_{i-1}^{k} \cdot C_{n-j}^{k}}$ 那么总的时间复杂度为 $O(n^3)$,显然会超时。事实上该组合式可以由范德蒙德卷积推导出 $\sum\limits_{k=0}^{\min\{i-1, n-j\}}{C_{i-1}^{k} \cdot C_{n-j}^{k}}= C_{i-1+n-j}^{i-1}$。

  首先有范德蒙德卷积 $\sum\limits_{i=0}^{k}{C_{n}^{i} \cdot C_{m}^{k-i}} = C_{n+m}^{k}$,具体证明可以参考链接。从组合意义上来讲的话,原本从大小为 $n+m$ 的集合中选出 $k$ 个元素,等价于把集合分别划分为大小为 $n$ 的集合与大小为 $m$ 的集合,先从大小为 $n$ 的集合中取出 $i \, (0 \leq i \leq k)$ 个元素,再从大小为 $m$ 的集合中取出 $k-i$ 个元素。

  现在假设 $k = m$,那么有 $\sum\limits_{i=0}^{m}{C_{n}^{i} \cdot C_{m}^{m-i}} = \sum\limits_{i=0}^{m}{C_{n}^{i} \cdot C_{m}^{i}} = C_{n+m}^{m} = C_{n+m}^{n}$。

  AC 代码如下,时间复杂度为 $O(n^2)$:

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 2005, mod = 1e9 + 7;

int a[N];
int c[N][N];

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    for (int i = 0; i <= n; i++) {
        for (int j = 0; j <= i; j++) {
            if (!j) c[i][j] = 1;
            else c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
        }
    }
    int ret = 0;
    for (int i = 1; i <= n; i++) {
        int p = 1;
        for (int j = i + 1; j <= n; j++) {
            if (a[i] != a[j]) ret = (ret + 1ll * p * c[i - 1 + n - j][i - 1]) % mod;
            p = 2ll * p % mod;
        }
    }
    cout << ret;
    
    return 0;
}

 

参考资料

  题解 | #周赛59题解#:https://www.nowcoder.com/discuss/662403130013868032

  范德蒙德卷积 - OI Wiki:https://oi-wiki.org/math/combinatorics/vandermonde-convolution/

标签:limits,cdot,sum,元素,小红,数组,回文
From: https://www.cnblogs.com/onlyblues/p/18404262

相关文章

  • 51nod 1050 循环数组最大子段和
    51nod1050循环数组最大子段和虽然是板子题,两种做法,我们先写一种,另一个咕咕。因为是循环,所以分为两种,中间的和两边的,中间的直接dp求最大,两边的转化一下就是总的数字和减去中间的最小数字和。#include<bits/stdc++.h>usingnamespacestd;#definelllonglonglla[500005]......
  • Java基础 | 数组 | 一维数组 | 二维数组 | 数组初始化 | 索引
    目录一维数组什么是数组数组定义格式格式一格式二数组初始化数组动态初始化什么是动态初始化动态初始化格式动态初始化格式详解等号左边等号右边数组静态初始化什么是静态初始化静态初始化格式完整版格式简化版格式示例代码数组元素访问什么是索引访问数......
  • 【C++学习笔记】数组与指针(三)
    目录一、数组1.1数组声明与赋值1.2数组的特点特点1:任意类型均可创建数组特点2:固定大小特点3:内存连续且有序特点4:C++无数组下标越界错误特点5:数组变量不记录数据1.3遍历数组普通for循环foreach增强循环1.4字符数组1.5多维数组二维数组三维数组遍历二维数......
  • 【算法笔记】树状数组/Binary Indexed Tree/Fenwick Tree
    前言树状数组,即树形存储的数组,又称BinaryIndexedTree或FenwickTree。抛开它树形的存储结构,这种神奇的数据结构的应用看起来与「树」没什么关系:有一个序列\(A=(A_1,A_2,\dots,A_N)\),在不超过\(\mathcalO(\logN)\)的时间复杂度内完成下列操作:\(\to~\)求\([L,R]\)区间内所......
  • 【算法笔记】【专题】RMQ 问题:ST表/树状数组/线段树
    0.前言好久没更算法笔记专栏了,正好学了新算法来更新……这也是本专栏的第一个专题问题,涉及到三种数据结构,如果写得有问题请各位大佬多多指教,谢谢!1.关于RMQ问题RMQ的全称是RangeMinimum/MaximumQuery,即区间最大/最小值问题。本文中,我们的算法以求最大值为例(最小值基本......
  • 977. 有序数组的平方
    给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。 示例1:输入:nums=[-4,-1,0,3,10]输出:[0,1,9,16,100]解释:平方后,数组变为[16,1,0,9,100]排序后,数组变为[0,1,9,16,100]示例2:输入:nums=[-7,-3,2,3,11]......
  • 有序数组的平方
    题目描述:给你一个按非递减顺序排序的整数数组nums,返回每个数字的平方组成的新数组,要求也按非递减顺序排序。示例1:输入:nums=[-4,-1,0,3,10]输出:[0,1,9,16,100]解释:平方后,数组变为[16,1,0,9,100]排序后,数组变为[0,1,9,16,100]示例2:输入:nums=[-7,-3,2,3,11]......
  • CTF逆向:将数组作为函数代码执行
    例题攻防世界BABYREflag判定条件为这个if(v5==14&&(*judge)(s))注意judge本质上是一个数组,(*judge)(s)则说明judge数组中的内容被当做代码执行但前面又有for(i=0;i<=181;++i)judge[i]^=0xCu;judge数组中的内容进行加密所以需要进行patch......
  • 6.跟着狂神学JAVA(数组)
    数组数组是相同类型数据的有序集合每一个数据称作一个数据元素,每个数组元素可以通过一个下标来访问获取数组长度:array.length数组的使用声明数组dataType[]arrayName;初始化数组在声明时初始化int[]numbers=newint[5];//创建一个长度为5的整型数组在声明......
  • C语言练习题--一维、二维字符串数组
    1.下列对C语言字符数组的描述中错误的是(D) A.字符数组可以存放字符串B.字符数组中的字符串可以整体输入、输出C.不可以用关系运算符对字符数组中的字符串进行比较D.可以在赋值语句中通过赋值运算符"="对字符数组整体赋值分析:D只能逐个字符进行复制或者利用字......