Wannafly挑战赛5 A.珂朵莉与宇宙

**

A.珂朵莉与宇宙

**
题目描述
星神是来自宇宙的
所以珂朵莉也是吧
所以我就出了个题
给你一个长为n的序列a,有n*(n+1)/2个子区间,问这些子区间里面和为完全平方数的子区间个数
输入描述:
第一行一个数n
第二行n个数表示序列a
输出描述:
输出一个数表示答案
示例1
输入

6
0 1 0 9 1 0
输出

11
备注:
1 <= n <= 100000
0 <= ai <= 10

解题思路:前缀和求解问题。看数据范围就知道一定有什么神秘操作。
a[]数组存放前缀和。 b[]数组作为标记(哪些前缀和出现过),O(n)跑一边,在每个i的位置枚举小于等于a[i]的平方数。
例如样例中, 我们举个栗子,现在到9,也就说 a[i] = 10, b[0] = 2, b[1] = 2。这是我们的已知条件,那么现在就要枚举从j = 0 开始, 第一个是 j = 0, a[i] - j*j = 10,
b[10] = 0; 第二个是 j = 1, a[i] - j* j = 9,b[9] = 0; 第三个是 j = 2, a[i] - j* j = 6,b[6] = 0; 第四个是 j = 3, a[i] - j*j = 1,b[1] = 2; -> res += 2.(为什么这里加2,第一种是 9,第二种是 0 和 9),当j = 4 的时候就退出循环。

理解到这里,这道题基本已经完成啦。
还需要注意到几个点: 对于复杂度的计算。 1 <= n <= 100000,0 <= ai <= 10, 最大的前缀和是 1e6, 枚举的最大值就是 1000,所以复杂度是 O(1e8),时间给了2s,足够。
第二点就是注意b[i]的数组大小和,res要用long long。

#include<bits/stdc++.h>
using namespace std;
int a[110000];
int b[1100000];
int main ()
{
    //yyy_3y
    int t; scanf("%d",&t);
    for (int i = 1; i <= t; i++){
        scanf("%d",&a[i]);
        a[i] += a[i-1];
    }
    long long  res = 0;
    b[0] = 1;
    for (int i = 1; i <= t; i++){
        for (int j = 0; j*j <= a[i]; j++){
            res += b[a[i] - j*j];
        }
        b[a[i]]++;
    }
    printf("%lld\n",res);
    return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值