为了更好的阅读体检,可以查看我的算法学习博客
在线评测链接:P1117
题目内容
塔子哥是一个游戏爱好者,他喜欢用数字和算法解决各种难题。有一天,他遇到了一个有趣的问题。他手头有一个环形数组 a a a ,数组中有 n n n 个数字。
他想玩一个游戏,用两刀把它切割成两段,使得两段的数字之和相等。他可以选择在任何两个数字之间切割,但是他必须确保切割的两段都不为空。
塔子哥非常聪明,很快就意识到这是一个非常有趣的问题。他开始思考如何解决这个问题,并且尝试了很多不同的方法,还是没有想出来如何解决。
于是,塔子哥想分享这个问题并且寻求你的帮助。他想知道有多少种不同的切割方案可以使得两段数字之和相等。
输入描述
第一行输入一个正整数 n n n ,代表环形数组的元素数量。
第二行输入 n n n 个正整数 a i a_i ai,代表环形数组的元素。
1 ≤ n ≤ 1 0 5 1\leq n\leq 10^5 1≤n≤105
− 1 0 9 ≤ a i ≤ 1 0 9 -10^9\leq a_i\leq 10^9 −109≤ai≤109
输出描述
一个整数,代表切割的方案数。
样例
输入
5
1 4 -2 5 2
输出
2
思路
哈希表计数
这种题目是一类经典题目。如果没见过,请跟着塔子哥的指引来:
先把这个题搞懂。
2.P1050 华东师范大学保研机试-2022-差分计数 并查看塔子哥的题解,里面有详细的解析和代码注释。并尝试解决题解中的<拓展>部分
回到这道题,唯一要注意的地方在于:由于题目要求了两段都不能为空,所以前缀和数组不能包括开始的 0 0 0,防止出现分割出空的情况。
代码
代码写的很好了,感觉不太需要注释~
CPP
#include <bits/stdc++.h>
using namespace std;
long long NumsOfScene(vector<long long>& nums) {
int n = nums.size();
long long target = accumulate(nums.begin(), nums.end(), 0);
if ( target%2 ) return 0;
target /= 2;
long long ans = 0, preSum[n+1] = {0};
for ( int i=0;i<n;++i ) preSum[i+1] = preSum[i] + nums[i];
unordered_map<long long,int> cnt;
for ( int i=1;i<n+1;++i ) {
int need = preSum[i]-target;
auto it = cnt.find(need);
if ( it!=cnt.end() ) ans += cnt[need];
cnt[preSum[i]]++;
}
return ans;
}
int main(void) {
int n;
cin >> n;
vector<long long> nums(n, 0);
for ( long long &x:nums ) cin >> x;
cout << NumsOfScene(nums) << endl;
return 0;
}
//by Unsigned_Gunn
python
n = int(input().strip())
nums = list(map(int, input().strip().split(' ')))
half_sum = sum(nums)/2
dp = {}
ans = 0
cur_sum = 0
for i in range(len(nums)):
cur_sum += nums[i]
if cur_sum not in dp:
dp[cur_sum] = 0
tar = cur_sum-half_sum
if tar in dp:
ans += dp[tar]
elif cur_sum==half_sum:
ans += 1
dp[cur_sum]+=1
print(ans)
Java
import java.util.HashMap;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int[] arr = new int[N];
long sum = 0;
for (int i = 0; i < N; i++) {
arr[i] = sc.nextInt();
sum+=arr[i];
}
if (sum % 2 != 0){
System.out.println(0);
return;
}
HashMap<Long,Integer> map = new HashMap<>();
sum = sum/2;
map.put((long) arr[0],1);
long tmp = arr[0];
long ans = 0;
for (int i = 1; i < N; i++) {
tmp+=arr[i];
if (map.containsKey(tmp-sum)){
ans+=map.get(tmp-sum);
}
map.put(tmp,map.getOrDefault(tmp,0)+1);
}
System.out.println(ans);
}
}
Go
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
sc := bufio.NewReader(os.Stdin)
var n int
fmt.Fscanln(sc, &n)
nums := []int{}
for i := 0; i < n; i++ {
var ai int
fmt.Fscan(sc, &ai)
nums = append(nums, ai)
}
fmt.Fscanln(sc)
test7(nums)
}
func test7(nums []int) {
sum := 0
for _, num := range nums {
sum += num
}
if sum&1 == 1 {
fmt.Println(0)
return
}
target := sum / 2
prefix := 0
prefixs := []int{}
for i := 0; i < len(nums); i++ {
prefix += nums[i]
prefixs = append(prefixs, prefix)
}
res := 0
hashMap := map[int]int{}
for i := 0; i < len(nums); i++ {
pre := prefixs[i] - target
if val, exist := hashMap[pre]; exist {
res += val
}
hashMap[prefixs[i]]++
}
fmt.Println(res)
}
Js
function NumsOfScene(nums) {
const n = nums.length;
const target = nums.reduce((acc,cur) => acc+cur, 0);
if ( target%2 ) return 0;
const half = target/2;
let ans = 0, preSum = new Array(n+1).fill(0);
for ( let i=0;i<n;++i ) preSum[i+1] = preSum[i] + nums[i];
const cnt = new Map();
for ( let i=1;i<n+1;++i ) {
const need = preSum[i]-half;
if ( cnt.has(need) ) ans += cnt.get(need);
cnt.set(preSum[i],(cnt.get(preSum[i]) || 0) + 1);
}
return ans;
}
process.stdin.resume();
process.stdin.setEncoding('utf-8');
let input = '';
process.stdin.on('data', (data) => {
input += data;
return;
});
process.stdin.on('end', () => {
const lines = input.trim().split('\n');
const n = parseInt(lines[0]);
const nums = lines[1].split(' ').map(x => parseInt(x));
console.log(NumsOfScene(nums));
});
题目内容均收集自互联网,如如若此项内容侵犯了原著者的合法权益,可联系我: (CSDN网站注册用户名: 塔子哥学算法) 进行删除。