1 e 5 1e5 1e5 的数据显然是不可暴力枚举的。 我们用 s [ r ] − s [ l − 1 ] s[r]-s[l-1] s[r]−s[l−1] 表示 [ l , r ] [l,r] [l,r] 的区间和,看数据范围我们知道 s [ i ] s[i] s[i] 最多为 1 0 6 10^6 106, 也就是说我们要的平方和最多不超过 1 0 3 10^3 103,那样的话我们就可以试着枚举n以及平方和, 然后记录值等于 s [ r ] − j 2 s[r]−j^2 s[r]−j2 的前缀和的个数即可得到答案。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
const int MAX = 1e5 * 10 + 10;
int cnt[MAX], s[N]; // cnt[]存储满足条件的区间出现的次数,s[]为前缀和数组
int main()
{
ll n, x, ans = 0;
cin >> n;
for(ll i = 1; i <= n; i ++){ // 初始化前缀和数组
cin >> x;
s[i] = s[i - 1] + x;
}
cnt[0] = 1;
for(ll i = 1; i <= n; i ++){
for(ll j = 0; j * j <= s[i]; j ++) // 从0到当前前缀和枚举完全平方数
ans += cnt[s[i] - j * j]; // 前缀和为s[i] - j * j的个数累加
cnt[s[i]] ++; // 更新当前前缀和出现的次数
}
cout << ans << endl;
return 0;
}