惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Threatpost
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
T
The Blog of Author Tim Ferriss
S
SegmentFault 最新的问题
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 司徒正美
T
Tailwind CSS Blog
The Cloudflare Blog
The Last Watchdog
The Last Watchdog
PCI Perspectives
PCI Perspectives
博客园 - 聂微东
Stack Overflow Blog
Stack Overflow Blog
TaoSecurity Blog
TaoSecurity Blog
云风的 BLOG
云风的 BLOG
C
Cybersecurity and Infrastructure Security Agency CISA
O
OpenAI News
Recorded Future
Recorded Future
GbyAI
GbyAI
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Y
Y Combinator Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
量子位
博客园 - 叶小钗
V
Vulnerabilities – Threatpost
F
Full Disclosure
Recent Announcements
Recent Announcements
Vercel News
Vercel News
S
Schneier on Security
H
Heimdal Security Blog
Cisco Talos Blog
Cisco Talos Blog
V2EX - 技术
V2EX - 技术
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
B
Blog RSS Feed
宝玉的分享
宝玉的分享
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
P
Privacy & Cybersecurity Law Blog
T
Threat Research - Cisco Blogs
G
Google Developers Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
爱范儿
爱范儿
IT之家
IT之家
大猫的无限游戏
大猫的无限游戏
C
Check Point Blog
N
Netflix TechBlog - Medium
S
Security @ Cisco Blogs
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Microsoft Azure Blog
Microsoft Azure Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Cyberwarzone
Cyberwarzone

博客园 - 糖豆爸爸

【树上DP前导知识汇总】 快速幂、龟速乘总结 反向建图+拓扑排序 卡特兰数专题(Catalan) AcWing 126. 最大的和 AcWing 431. 守望者的逃离 AcWing 414. 数字游戏 AcWing 468. 魔法阵 洛谷 P1632 点的移动 P1056 NOIP2008 普及组 排座椅 洛谷 P1889 士兵站队 洛谷 P1862 输油管道问题 CF444C DZY Loves Colors P2253 好一个一中腰鼓! SCOI2010 P2572 序列操作 P4344 SHOI2015 脑洞治疗仪 T125847 【模板】动态开点线段树 P3373 【模板】线段树 2 Physical Education Lessons
AcWing 463. 求和
糖豆爸爸 · 2023-09-26 · via 博客园 - 糖豆爸爸

\(AcWing\) \(463\). 求和

一、题目描述

一条狭长的纸带被均匀划分出了 \(n\) 个格子,格子编号从 \(1\)\(n\)

每个格子上都染了一种颜色 \(color_i\)(用 \([1,m]\) 当中的一个整数表示),并且写了一个数字 \(number_i\)

定义一种特殊的三元组:\((x,y,z)\),其中 \(x,y,z\)
都代表纸带上格子的编号,这里的三元组要求满足以下两个条件:

  • \(x,y,z\) 都是整数, \(x<y<z,y−x=z−y\)
  • \(color_x=color_z\)

满足上述条件的三元组的分数规定为 \((x+z)∗(number_x+number_z)\)

整个纸带的分数规定为所有满足条件的三元组的分数的和。

这个分数可能会很大,你只要输出整个纸带的分数除以 \(10,007\) 所得的余数即可。

输入格式
第一行是用一个空格隔开的两个正整数 \(n\)\(m\)\(n\) 代表纸带上格子的个数,\(m\) 代表纸带上颜色的种类数。

第二行有 \(n\) 个用空格隔开的正整数,第 \(i\) 个数字 \(number_i\) 代表纸带上编号为 \(i\) 的格子上面写的数字。

第三行有 \(n\) 个用空格隔开的正整数,第 \(i\) 个数字 \(color_i\) 代表纸带上编号为 \(i\) 的格子染的颜色。

输出格式
共一行,一个整数,表示所求的纸带分数除以 \(10,007\)所得的余数。

数据范围
\(1≤n,m≤10^5,1≤number_i≤10^5\),
\(1≤color_i≤m\)

输入样例

6 2
5 5 3 2 2 2
2 2 1 1 2 1

输出样例

82

二、暴力枚举

\(40\)\(O(n^2)\)

三元组:\((x, y, z)\)要求满足以下两个条件:

  • \(x,y,z\) 都是整数, \(x<y<z,y−x=z−y\)
  • \(color_x=color_z\) 那么:\(x+z=2y\)。由此可以枚举\(x\)\(y\)的值,如果颜色相同,累加分值即可。

时间复杂度
\(O(n^2)\)

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

const int N = 100010, mod = 10007;

int a[N], color[N];

int main() {
    int n, m; // 纸带上格子的个数,纸带上颜色的种类数
    cin >> n >> m;

    for (int i = 1; i <= n; i++) cin >> a[i];     // 纸带上编号为 i 的格子上面写的数字
    for (int i = 1; i <= n; i++) cin >> color[i]; // 纸带上编号为 i 的格子染的颜色

    int res = 0;
    for (int x = 1; x <= n; x++) {
        for (int y = x + 1; 2 * y - x <= n; y++) { // 因为y>=x+1,并且z<=n
            int z = 2 * y - x;
            if (color[x] == color[z]) // 如果color[x]=color[z]
                res = (res + (2 * y) % mod * (a[x] + a[z]) % mod) % mod;
        }
    }
    printf("%d\n", res);
    return 0;
}

三、优化

读题,我们发现完全可以暴力\(O(n^{3})\)

那这必然过不了

观察题目,对式一进行移项,发现\(x+z=2y\)

于是我们便可以枚举\(x,z\)\(y\)

当然这个复杂度也是过不了的

做到这个地步,我们似乎基本没有用到颜色

于是我们便可以向颜色上靠,可以利用 分组 的思想,将同一颜色分成一组,又根据\(x+z=2y\)

可以 把相同颜色的分为奇偶两组

\(Q\):怎么得出最后答案呢?

我们可以对分数的计算:\((x+z)*(number_{x}+number_{z})\) 进行一定的处理(数学变形)

  • \(c[i]\)为第\(i\)个格子的颜色
  • \(cnt[c[i]][i\%2]\)为颜色为\(c[i]\)的两个奇偶分组中数字个数

\(x_i\)为下标,\(w_i\)为值

\(ans=(x_1+x_2)(w_1+w_2)+(x_1+x_3)(w_1+w_3)+…+(x_1+x_n)(w_1+w_n) \\ \ \ \ \ \ \ \ \ \ +(x_2+x_3)(w_2+w_3)+(x_2+x_4)(w_2+w_4)+…+(x_2+x_n)(w_2+w_n)\\ \ \ \ \ \ \ \ \ \ +(x_3+x_4)(w_3+w_4)+…+(x_3+x_n)(w_3+w_n)\\ \ \ \ \ \ \ \ \ \ +… \\ \ \ \ \ \ \ \ \ \ +(x_{n−1}+x_n)(w_{n−1}+w_n)\)

将有关\(x_1\)的式子 提出来找规律

\((x_1+x_2)*(w_1+w_2) +(x_1+x_3)*(w_1+w_3)...+ (x_1+x_n)*(w_1+w_n)\)

注:共\(n-1\)

乘出来
\(x_1 * w_1 + x_1 * w_2 +x_2 * w_1+x_2 * w_2+ \\ x_1 * w_1 + x_1 * w_3 +x_3 * w_1+x_3 * w_3+ \\ ... \\ +x_1 * w_1+ x_1*w_n+x_n*w_1+x_n*w_n\)

将有关\(x_1\)的式子提出来

\(x_1*w_1+x_1*w_2+...+x_1*w_1+x_1*w_n\)

\(=(n-1)*x_1*w_1+x_1*(w_2+w_3+...+w_n)\)

将这个式子
\(+x_1*w_1-x_1*w_1\)

\(\displaystyle \ \ \ \ \ \ (n-2)*x_1*w_1+x_1*(w_1+w_2+w_3+...+w_n) \\ = x_1*((n-2)*w_1+(w_1+w_2+w_3+...+w_n)) \\ = x_1*[(n-2)*w_1+\sum_{i=1}^nw_i]\)

显然\(\displaystyle \sum_{i=1}^nw_i\)可以预处理出来。
这个 \(n-2\)是什么呢?\(n\)应该是该分组中数字的总个数,这个也可以预处理出来~

\(Code\)

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

const int N = 100010, mod = 10007;

int w[N]; // 第i个格子的数字
int c[N]; // 第i个格子的颜色
int s[N][2];
// s[i][0]:颜色为i、编号为偶数格子上数字的和
// s[i][1]:颜色为i、编号为奇数格子上数字的和

int cnt[N][2];
// cnt[i][0]:颜色为i、编号为偶数格子的个数
// cnt[i][1]:颜色为i、编号为奇数格子的个数

int main() {
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i++) cin >> w[i]; // 第i个格子的数字
    // 预处理
    for (int i = 1; i <= n; i++) { // 遍历每个格子
        cin >> c[i];               // 格子颜色c[i]
        /*
        装入不同的组中,组划分是两个规则:
        ① 颜色必须相同
        ② 奇偶性必须相同
        所以,c[i]相同的放到同一个颜色组内,并且,在同一个颜色组内,奇偶数还必须相同。

        s[][]:随着i的不断向后遍历,s中记录了相同颜色,相同奇偶性的格子,数字的累加和
        cnt[][]:记录每个分组中的格子个数
        */
        s[c[i]][i % 2] = (s[c[i]][i % 2] + w[i]) % mod; // 累加分组内数字和
        cnt[c[i]][i % 2]++;                             // 维护分组内格子个数
    }

    int ans = 0;
    for (int i = 1; i <= n; i++) // 枚举每个格子
        /*
        Q:这个格子在哪个分组里呢?
        答:
        (1) c[i] : 按颜色划分
        (2) i % 2 : 按奇偶性划分

        Q:这个分组中格子的数量是多少呢?
        答: cnt[c[i]][i % 2]

        */
        ans = (ans + i * ((cnt[c[i]][i % 2] - 2) * w[i] % mod + s[c[i]][i % 2])) % mod;

    printf("%d\n", ans);
    return 0;
}