前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Wannafly挑战赛27 A-灰魔法师(思维)

Wannafly挑战赛27 A-灰魔法师(思维)

作者头像
Ch_Zaqdt
发布2019-01-10 17:06:21
3250
发布2019-01-10 17:06:21
举报
文章被收录于专栏:Zaqdt_ACMZaqdt_ACM

题目链接:https://www.nowcoder.com/acm/contest/215/A

       这道题暴力肯定是过不了的,然后就有一种很巧妙地方法,因为数据范围只有1e5,两个数相加最大也只有2e5,然后2e5的数据中,完全平方数的个数其实只有几百个,所以我们可以将2e5范围内的完全平方数先打个表存起来,然后对于输入的n个数,我们只需要记录它出现的个数,然后我们去枚举1-100000中的数。

       对于接下来的操作,分为两种情况,一种是2 2 2,对于有3个2的情况,它符合条件的个数为3(就是3*(3-1)/2),另一种情况是1 1 3 3,这样的话符合情况的个数就是2(因为不能重复),这种情况的解就是pre[1] * pre[3] / 2。所以我们只需要对于这两种情况讨论就行了。

       还有一个小坑点就是在第二种情况的时候,我们要先把所有的第二种情况算出来以后再除以2,不然会有精度损失(详细看呆码),还有改用ll的地方记得用ll。

       有一点不太明白不知道为啥我的num不能从0开始,这一点wa了n发...很巧妙的一道题...


AC代码:

代码语言:javascript
复制
#include <bits/stdc++.h>
#define maxn 100000
#define ll long long
using namespace std;
int pre[maxn],a[maxn];
int n,num;
  
int main()
{
  scanf("%d",&n);
  num = 1;    // 不知道为啥不能从0开始...
  for(int i=1;i*i<=200000;i++){
    a[num++] = i * i;
  }
  memset(pre,0,sizeof(pre));
  for(int i=0;i<n;i++){
    int x;
    scanf("%d",&x);
    pre[x] ++;
  }
  ll sum = 0,sum1 = 0;
  for(int i=1;i<=num;i++){
    for(int j=1;j<=maxn;j++){
      if(pre[j] == 0) continue;
      int ans = a[i] - j;
      if(ans > maxn) continue;
      if(ans <= 0) break;
      if(pre[ans]){
        if(ans == j) sum1 += ((ll)pre[j] * (ll)(pre[j] - 1)) / 2;
        else sum += (ll)pre[ans] * (ll)pre[j];    // 这里不要除以2,会有精度损失
      }
    }
  }
  printf("%lld\n",sum1 + sum / 2);
  return 0;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年11月01日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档