Wannafly挑戰賽27 A 灰魔法師

鏈接:https://www.nowcoder.com/acm/contest/215/A
來源:牛客網
 

題目描述

“White shores, and beyond. A far green country under a swift sunrise.”--灰魔法師

給出長度爲n的序列a, 求有多少對數對 (i, j) (1 <= i < j <= n) 滿足 ai + aj 爲完全平方數。

輸入描述:

第一行一個整數 n (1 <= n <= 105)
第二行 n 個整數 ai (1 <= ai <= 105)

輸出描述:

輸出一個整數,表示滿足上述條件的數對個數。

 

示例1

輸入

複製

3
1 3 6

輸出

複製

2

思路:首先能想到ai+aj最大和也就是2e5,同時2e5以內的平方數只有400多個,可以直接打表存下來,記爲p[i]。

然後我們把每個a[i]做標記(同時統計個數),用p[i]去掃描a[i],已知p[1],令p[1]-ai,所得差即爲另一個數aj,如果能在a[i]裏找到(即a[j]被標記),說明這個平方和p[1]成立。複雜度O(1e2*1e5)。

接下來需要考慮兩種情況:

1。完全相同的數組合:2 2 2    此時方案是3,我們標記數組應該是vis[2]=3,那麼都是相同的數字,任選兩個的方案數:C[3,2],即(n*(n-1))/2

2.不同的數字組合:1 1 3 3   此時方案是4,標記數組vis[1]=2,vis[3]=2,直接vis[1]*vis[3]就是方案數,由於重複計算(vis[3]*vis[1]),這個情況的答案需要/2,1情況不需要。

總之就是結果統計需要考慮相同數字的情況,情況就這兩種- -。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll vis[100010],n,a[1010],pos,ans1,ans2;
ll ans;
int main()
{
    pos=1;
    for(ll i=1;i*i<=200000;i++)a[pos++]=i*i;   //生成平方數
    while(~scanf("%lld",&n))
    {
        memset(vis,0,sizeof(vis));
        ll x;
        for(ll i=1;i<=n;i++)
        {
            scanf("%lld",&x);
            vis[x]++;   //統計個數
        }
        ans1=ans2=0;
        ll tmp;
        for(ll i=1;i<pos;i++)   //平方數數組
        {
            for(ll j=1;j<=100000;j++)   //1e5以內所有數
            {
                if(vis[j]==0)continue;  
                tmp=a[i]-j;
                if(tmp>100000)continue;   //不合法範圍
                if(tmp<=0)break;   //不合法
                if(vis[tmp])
                {
                    if(tmp==j)ans1+=(vis[j]*(vis[j]-1))/2;   //相同時用組合公式
                    else ans2+=vis[tmp]*vis[j];   //不同時直接乘
                }
            }
        }
        ans1=ans1+ans2/2;
        printf("%lld\n",ans1);
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章