码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2017-12-09 21:04:02      阅读:140      评论:0      收藏:0      [点我收藏+]

标签:ace   sed   max   完全   return   printf   one   splay   技术   

题意 : 给你一个长为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

 

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

标签:ace   sed   max   完全   return   printf   one   splay   技术   

原文地址:http://www.cnblogs.com/Rubbishes/p/8012379.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!