牛客网 珂朵莉与宇宙(思维)

题意 : 给你一个长为n的序列a,有n*(n+1)/2个子区间,问这些子区间里面和为完全平方数的子区间个数。1 <= n <= 100000、0 <= ai <= 10

 

分析 : 题目的枚举对象是子区间的和,自然想到构造前缀和数组去进行操作(任意子区间的和都能由某两个前缀和做差得到)。由于这里每个元素都是大于或等于 0 的,所以前缀和肯定是单调不减的(由于有 0 的存在,所以不一定是单调递增),接下来从小到大枚举每一个前缀和,对于当前枚举的每一个前缀和 sum(now) 而言,其能与前面已经出现的前缀和构成的最大完全平方数必然不超过本身,即 sum(now) - sum( ? ) == num*num ,移项之后就能得到 sum(now) - num*num == sum( ? ) ,即前面是否有出现过值为 sum(now) - num*num 这样的前缀和,如果有,说明必定能凑成完全平方数 num*num ,而我们枚举 num*num 的上限完全可以限制在 sum(now) 以内。

 

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 10;
int Cnt[maxn];
 
int main(void)
{
    Cnt[0] = 1;
 
    int n, tmp, PreFixSum = 0;
    long long ans = 0;
 
    scanf("%d", &n);
    for(int i=0; i<n; i++){
        scanf("%d", &tmp);
        PreFixSum += tmp;
        for(int j=0; j*j<=PreFixSum; j++)
            if(Cnt[PreFixSum - j*j])
                ans += Cnt[PreFixSum - j*j];
        Cnt[PreFixSum]++;
    }
    printf("%lld\n", ans);
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/LiHior/p/8012379.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值