蓝桥杯OJ359求和【2022年蓝桥杯省赛真题】【动态规划压轴题】【详解是用ai生成的】

题目:

https://www.lanqiao.cn/problems/359/learning/?page=1&first_category_id=1&name=%E6%B1%82%E5%92%8Chttps://www.lanqiao.cn/problems/359/learning/?page=1&first_category_id=1&name=%E6%B1%82%E5%92%8C

可执行代码:

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;//数组长度 
const int p=10007;//取模 
long long num[N],col[N];
long long inum[N][2],Num[N][2],I[N][2],cnt[N][2];//【二维中的列[2]表示的都是区分奇数[i%2==1]还是偶数[i%2==0]】第一个表示当前的元素下标(x)*该下标(x)对应的元素的num[x]值;
//第二个表示所有的num[i]之和【区分奇偶】;第三个表示所有的i之和【区分奇偶】;第四个表示同颜色、同奇偶的元素数量 + 1 ,避免第23行代码多算了次数【区分奇偶】 
int main(){
long long n=0,m=0;cin>>n>>m;
for(int i=1;i<=n;i++){
	 cin>>num[i];
	 num[i]%=p; 
}
for(int i=1;i<=n;i++) cin>>col[i];
long long ans=0;//最终答案 
for(int i=1;i<=n;i++){
int x=i%2;
int c=col[i];
//导入当前数据【第一次导入的都是0】 
ans=(ans+inum[c][x])%p;
ans=(ans+(i*Num[c][x]%p)%p)%p;
ans=(ans+(num[i]*I[c][x]%p)%p)%p;
ans=(ans+(i*num[i]%p*cnt[c][x])%p)%p;
//更新数据,方便下一次导入 
inum[c][x]=(inum[c][x]+(i*num[i])%p)%p;
Num[c][x]=(Num[c][x]+num[i])%p;
I[c][x]=(I[c][x]+i)%p;
cnt[c][x]+=1;
}	
cout<<ans;	
	return 0;
} 

思路及代码解析:

这道题的完整讲解:同色同奇偶与前缀和优化

这道题最清晰、最详细、最容易听懂的完整讲解

我保证你看完彻底懂,以后遇到同类题直接秒写!

一、先搞懂题目到底要什么

题目:

给你一排 n 个位置

每个位置有:

  • 数字 numi
  • 颜色 coli

要求找所有三元组 (x, y, z) 满足:

  1. x < y < z
  1. y - x = z - y → 也就是 x 和 z 奇偶相同
  1. colx == colz
  1. 分数 = (x + z) × (numx + numz)
  1. 把所有满足条件的分数加起来,模 10007 输出

二、为什么暴力会超时?

暴力要两层循环:

|-------------------------------------------------------------------------|
| C++ for(x=1;x<=n;x++) for(z=x+2;z<=n;z++) if(同奇偶 && 同颜色) ans += ... |

n=1e5 → 100亿次循环 → 直接超时

所以必须用 O(n) 前缀和优化

三、核心数学公式(必须看懂)

题目要求:

|---------------------------------------------|
| Plain Text (x + z) * (numx + numz) |

展开后:

|-----------------------------------------------------|
| Plain Text (x+z)*(a+b) = x*a + x*b + z*a + z*b |

(a=numx, b=numz

这四项,我们可以用前缀和一次性算完

四、代码里四个数组的作用(最关键)

|-----------------------------------------------------------------------------------------------------------------|
| C++ sumcx = 累计 i * numi isumcx = 累计 numi poscx = 累计 下标 i cntcx = 累计 个数 |

其中:

  • c = 颜色
  • x = 下标奇偶(0偶 / 1奇)

一句话:

按【颜色+奇偶】分组,每组存4个前缀和

五、代码逐行详细运行过程

1. 输入部分

|------------------------------------------------------------------------------------------------------------------|
| C++ cin >> n >> m; for (int i=1; i<=n; i++) cin >> numi; for (int i=1; i<=n; i++) cin >> coli; |

读入 n、m、每个位置的数字、颜色。

2. 遍历每个位置 i(当作 z)

|---------------------------------|
| C++ for (int i=1; i<=n; i++) { |

我们把当前遍历到的 i 当作 z

前面所有满足条件的 x 都已经被记录在前缀和里了!

3. 获取当前颜色和奇偶

|-------------------------------------------------------------|
| C++ int x = i % 2; // 0=偶数位,1=奇数位 int c = coli; // 当前颜色 |

只有 同颜色 + 同奇偶 的 x 才能和当前 i 配对!

4. 直接用前缀和算四项贡献(O(1))

|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| C++ // 第1项:x*a ans += sumcx; // 第2项:x*b ans += i * isumcx; // 第3项:z*a ans += numi * poscx; // 第4项:z*b ans += i * numi * cntcx; |

这四行 = 暴力两层循环的所有结果!

5. 把当前 i 加入前缀和(给后面用)

|---------------------------------------------------------------------------------------------------------|
| C++ sumcx += i * numi; isumcx += numi; poscx += i; cntcx += 1; |

相当于把当前 i 存起来,让后面的 z 可以直接用它算贡献。

六、最直观的总结(背这个就够)

整个代码只做两件事:

  1. 算当前 i 与前面所有合法 x 的贡献
  1. 把当前 i 存进前缀和

时间复杂度:

O(n) ------ 1e5 数据秒过

七、你给的代码 = 完美标准AC代码

你现在这段代码:

|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| C++ #include <bits/stdc++.h> using namespace std; #define int long long const int N = 1e5 + 9; const int p = 10007; int numN, colN; int sumN2, isumN2, posN2, cntN2; signed main() { ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int n, m;cin >> n >> m; for (int i = 1; i <= n; i++)cin >> numi, numi %= p; for (int i = 1; i <= n; i++)cin >> coli; int ans = 0; for (int i = 1; i <= n; i++) { int x = i % 2; int c = coli; ans = (ans + sumcx) % p; ans = (ans + (i * isumcx) % p) % p; ans = (ans + (numi * poscx) % p) % p; ans = (ans + (i * numi % p * cntcx) % p) % p; sumcx = (sumcx + (i * numi) % p) % p; isumcx = (isumcx + numi) % p; poscx = (poscx + i) % p; cntcx++; } cout << ans << endl; return 0; } |

✅ 100% 正确

✅ 时间复杂度最优 O(n)

✅ 蓝桥杯 / 天梯赛 标准满分写法

相关推荐
2601_961194022 天前
教资科三美术考什么|初中高中美术题型考点和模板资料
leetcode·elasticsearch·职场和发展·蓝桥杯·pat考试·lucene
h_a_o777oah2 天前
2026 蓝桥杯软件 C++B组 国赛比赛经历及备赛建议
c++·经验分享·算法·蓝桥杯
迈巴赫车主2 天前
蓝桥杯21241灯塔java
java·开发语言·数据结构·算法·职场和发展·蓝桥杯·动态规划
大学竞赛君3 天前
第十六届蓝桥杯大赛软件赛决赛 Python 大学 A 组
python·职场和发展·蓝桥杯
此生决int4 天前
算法从入门到精通——字符串
数据结构·c++·算法·蓝桥杯
飞天狗1115 天前
2024第十五届蓝桥杯c/c++B组国赛题解
c语言·数据结构·c++·算法·蓝桥杯
casual~5 天前
十六届蓝桥杯国赛个人题解
经验分享·学习·算法·蓝桥杯
wanderist.6 天前
14决赛蓝桥杯
职场和发展·蓝桥杯
飞天狗1118 天前
2025第十六届蓝桥杯c/c++B组国赛题解
c语言·c++·算法·蓝桥杯
迈巴赫车主10 天前
蓝桥杯21247弹跳鞋java
java·开发语言·数据结构·算法·职场和发展·蓝桥杯