【题目来源】
http://oj.ecustacm.cn/problem.php?id=1781
http://oj.ecustacm.cn/viewnews.php?id=1023
【题目描述】
给你一个长度为 n 的序列,序列中的元素只包括 1 和 -1。
请问有多少个连续的子序列乘积为正数。
【输入格式】
输入第一行为正整数 n。(n不超过10^6)
第二行包含 n 个整数。
【输出格式】
输出一个数字表示答案。
【输入样例】
4
1 1 -1 -1
【输出样例】
6
【算法分析】
● 动态规划
最后一步法:https://blog.csdn.net/hnjzsyjyj/article/details/112797538
本题是“计数型”问题,可采用动态规划算法求解。
(1)确立状态
设输入的序列是 a[1]~a[n],依据最后一步法,可定义 DP 状态为:
f[i][0]:以 a[i] 结尾的积为 -1 的连续子序列个数
f[i][1]:以 a[i] 结尾的积为 1 的连续子序列个数
例如,针对样例 {1, 1, -1, -1},有 f[1][1]=1,f[2][1]=2,f[3][1]=0,f[4][1]=3。
(2)状态转移方程
若a[i]=1:
f[i][1]=f[i-1][1]+1,积为 1 的连续子序列个数加 1
f[i][0]=f[i-1][0],积继续为 -1
若a[i]=-1:
f[i][1]=f[i-1][0]
f[i][0]=f[i-1][1]+1
最后,把所有 f[i][1] 相加,就是答案。
【算法代码】文章来源:https://www.toymoban.com/news/detail-668449.html
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
int a[maxn];
long long f[maxn][2];
long long ans;
int main() {
int n;
cin>>n;
for(int i=1; i<=n; i++) cin>>a[i];
for(int i=1; i<=n; i++) {
if(a[i]==1) {
f[i][1]=f[i-1][1]+1;
f[i][0]=f[i-1][0];
} else if(a[i]==-1) {
f[i][1]=f[i-1][0];
f[i][0]=f[i-1][1]+1;
}
}
for(int i=1; i<=n; i++) ans=ans+f[i][1];
cout<<ans<<endl;
return 0;
}
/*
in:
4
1 1 -1 -1
out:
6
*/
【参考文献】
https://blog.csdn.net/weixin_43914593/article/details/131810636
https://blog.csdn.net/hnjzsyjyj/article/details/112797538
文章来源地址https://www.toymoban.com/news/detail-668449.html
到了这里,关于罗勇军 →《算法竞赛·快冲300题》每日一题:“乘积” ← 动态规划的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!