AT1894 総和(暴力,前缀和)
输入两个整数n,k;
给出一个长度为N的数列a[1]-a[n].
求这个数列中所有长度为K的连续的部分的总和
输入输出样例
输入 #1复制
5 3
1 2 4 8 16
输出 #1复制
49
输入 #2复制
20 10
100000000 100000000 98667799 100000000 100000000 100000000 100000000 99986657 100000000 100000000 100000000 100000000 100000000 98995577 100000000 100000000 99999876 100000000 100000000 99999999
输出 #2复制
10988865195
制约:
1 ≤ K ≤ N ≤ 10^5
0< ai < 10^8
暴力算法模拟过程:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n, k;
cin >> n >> k;
vector<long long> s(n);
for (int i = 0; i < n; i++)
cin >> s[i];
long long sum = 0;
for (int i = 0; i <= n - k; i++)
{
for (int j = 0; j < k; j++)
{
sum += s[i + j];
}
}
cout << sum << endl;
}
前缀和算法:
解释:要想获取一个数组L到R区间的值的和,先将到ai的和存在s数组中,然后用s[R] - s[L-1]
cin >> a[i];//伪码
s[0] = a[0];
for(int i = 0; i < n; i++)
s[i] = s[i - 1] + a[i];
差分为前缀和的逆算法:
a[i] = s[i] - s[i-1]
前缀和解法:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n, k;
cin >> n >> k;
vector<long long> s(n);
for (int i = 0; i < n; i++)
cin >> s[i];
vector<long long> total(n);
total[0] = s[0];
for (int i = 1; i < n; i++)
{
total[i] = total[i - 1] + s[i]; //total[i]表示a[0]到a[i]的和;
}
long long sum = 0;
sum += total[k - 1];
for (int i = k; i < n; i++)
{
sum += total[i] - total[i - k];
}
cout << sum << endl;
}