" Algorithm Competition: 300 Quick Questions " will be published in 2024, and it is an auxiliary workbook for "Algorithm Competition" .
All questions are placed in the self-built OJ New Online Judge .
The codes are provided in C/C++, Java, and Python. The topics are mainly low-to-medium level, suitable for beginners and advanced.
Article directory
" Product ", link: http://oj.ecustacm.cn/problem.php?id=1781
topic description
[Title description] You are given a sequence of length n, and the elements in the sequence only include 1 and -1.
How many consecutive subsequences have a positive product.
【Input format】 Enter the first row as a positive integer n. (n does not exceed 10^6)
The second line contains n integers.
[Output Format] Output an integer to represent the answer.
【Input sample】
4
1 1 -1 -1
【Example of output】
6
answer
This is a classic question. The multiplication of an even number of -1s is a positive number, and the multiplication of an odd number of -1s is a negative number. This question can obviously be done with DP, and the DP state and transition equations are designed below.
Let the input sequence be a[1]~a[n], define the DP state as:
dp[i][0]: the number of products ending with a[i] is 1 dp[i][1]: the number of products ending with a[i] being -1 For
example, {1
, 1, -1, -1} of the sample, there are: dp[1][0]=1, dp[2][0]=2, dp[3][0]=0, dp[4 ][0]=3. The total computational complexity of DP is O(n). There are other solutions to this question, please think for yourself. 【Key Point】 Linear DP.
C++ code
#include<bits/stdc++.h>
using namespace std;
const int N = 1000010;
int a[N];
long long dp[N][2]; //dp[i][0]:以a[i]结尾的积为1的个数;dp[i][1]:以a[i]结尾的积为-1的个数
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){
dp[i][0] = dp[i-1][0] + 1; //积为1的个数再加1(就是加自己)
dp[i][1] = dp[i-1][1]; //积继续为-1,只能1乘以积为-1的dp
}
else if(a[i] == -1){
dp[i][0] = dp[i-1][1]; // -1乘以积为-1的dp ,积才为1
dp[i][1] = dp[i-1][0] + 1; // -1 乘以积为1的dp,积才为-1, 再加上1(自己)
}
}
for(int i=1;i<=n;i++) ans = ans + dp[i][0]; //将所有积为1的dp求和,即为总个数
cout << ans << endl;
return 0;
}
java code
import java.util.Scanner;
public class Main {
static final int N = 1000010;
static int[] a = new int[N];
static long[][] dp = new long[N][2];
//dp[i][0]:以a[i]结尾的积为1的个数;dp[i][1]:以a[i]结尾的积为-1的个数
static long ans;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
for (int i = 1; i <= n; i++) a[i] = sc.nextInt();
for (int i = 1; i <= n; i++) {
if (a[i] == 1) {
dp[i][0] = dp[i - 1][0] + 1; //积为1的个数再加1(就是加自己)
dp[i][1] = dp[i - 1][1]; //积继续为-1,只能1乘以积为-1的dp
} else if (a[i] == -1) {
dp[i][0] = dp[i - 1][1]; // -1乘以积为-1的dp ,积才为1
dp[i][1] = dp[i - 1][0] + 1; // -1 乘以积为1的dp,积才为-1, 再加上1(自己)
}
}
for (int i=1; i<=n; i++) ans += dp[i][0]; //将所有积为1的dp求和,即为总个数
System.out.println(ans);
}
}
Python code
N = 1000010
a = [0] * N
dp = [[0] * 2 for _ in range(N)]
# dp[i][0]:以a[i]结尾的积为1的个数;dp[i][1]:以a[i]结尾的积为-1的个数
ans = 0
n = int(input())
a[1:n + 1] = list(map(int, input().split()))
for i in range(1, n + 1):
if a[i] == 1:
dp[i][0] = dp[i - 1][0] + 1 # 积为1的个数再加1(就是加自己)
dp[i][1] = dp[i - 1][1] # 积继续为-1,只能1乘以积为-1的dp
elif a[i] == -1:
dp[i][0] = dp[i - 1][1] # -1乘以积为-1的dp ,积才为1
dp[i][1] = dp[i - 1][0] + 1 # -1 乘以积为1的dp,积才为-1, 再加上1(自己)
for i in range(1, n+1): ans += dp[i][0] # 将所有积为1的dp求和,即为总个数
print(ans)