小红的数组回文值

小红的数组回文值

题目描述

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

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

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

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

输入描述:

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

第二行输入 n 个整数 a1,a2,,an (1ai109) 代表数组元素。

输出描述:

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

示例1

输入

3
1 2 3

输出

4

说明

1,21,32,31,2,3 的回文值都是 1。其余子序列的回文值均为 0

示例2

输入

4
999 999 999 999

输出

0

 

解题思路

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

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

  先假设 aiaj 在子序列中就是对称的元素,首先对于 ai+1aj1 中的元素可以任意选择,不会改变 aiaj 的对称性,有 2ji1 种方案。然后考虑左边 a1ai1 和右边 aj+1an 的选择,显然两边应该选择同等数量的元素,那么可选的方案数量为 k=0min{i1,nj}Ci1kCnjk。因此以 aiaj 为对称元素的子序列的数量就是 2ji1k=0min{i1,nj}Ci1kCnjk

  最后总的答案就是i=1nj=i+1n[aiaj](2ji1k=0min{i1,jn}Ci1kCjnk)

  如果直接暴力计算 k=0min{i1,nj}Ci1kCnjk 那么总的时间复杂度为 O(n3),显然会超时。事实上该组合式可以由范德蒙德卷积推导出 k=0min{i1,nj}Ci1kCnjk=Ci1+nji1

  首先有范德蒙德卷积 i=0kCniCmki=Cn+mk,具体证明可以参考链接。从组合意义上来讲的话,原本从大小为 n+m 的集合中选出 k 个元素,等价于把集合分别划分为大小为 n 的集合与大小为 m 的集合,先从大小为 n 的集合中取出 i(0ik) 个元素,再从大小为 m 的集合中取出 ki 个元素。

  现在假设 k=m,那么有 i=0mCniCmmi=i=0mCniCmi=Cn+mm=Cn+mn

  AC 代码如下,时间复杂度为 O(n2)

#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/

posted @   onlyblues  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
历史上的今天:
2022-09-09 【转载】论递归算法的数学原理
Web Analytics
点击右上角即可分享
微信分享提示