Codeforces Round #572 (Div. 1) B. Count Pairs

本文详细解析了B.CountPairs算法,介绍了如何通过变形处理求解特定数学问题,即寻找满足特定模运算条件的数对数量。算法巧妙地利用桶排序思想,通过一次扫描完成计算,避免了传统方法的复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

B. Count Pairs

time limit per test

4 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

You are given a prime number pp, nn integers a1,a2,…,ana1,a2,…,an, and an integer kk.

Find the number of pairs of indexes (i,j)(i,j) (1≤i<j≤n1≤i<j≤n) for which (ai+aj)(a2i+a2j)≡kmodp(ai+aj)(ai2+aj2)≡kmodp.

Input

The first line contains integers n,p,kn,p,k (2≤n≤3⋅1052≤n≤3⋅105, 2≤p≤1092≤p≤109, 0≤k≤p−10≤k≤p−1). pp is guaranteed to be prime.

The second line contains nn integers a1,a2,…,ana1,a2,…,an (0≤ai≤p−10≤ai≤p−1). It is guaranteed that all elements are different.

Output

Output a single integer — answer to the problem.

Examples

input

Copy

3 3 0
0 1 2

output

Copy

1

input

Copy

6 7 2
1 2 3 4 5 6

output

Copy

3

Note

In the first example:

(0+1)(02+12)=1≡1mod3(0+1)(02+12)=1≡1mod3.

(0+2)(02+22)=8≡2mod3(0+2)(02+22)=8≡2mod3.

(1+2)(12+22)=15≡0mod3(1+2)(12+22)=15≡0mod3.

So only 11 pair satisfies the condition.

In the second example, there are 33 such pairs: (1,5)(1,5), (2,3)(2,3), (4,6)(4,6).

题意:满足题面公式对数有多少个,条件必须满足 i < j。

思路:公式题多考虑变形,扫一遍即可。左右乘上(ai - aj)可得 :

(ai - aj)*(ai + aj)(ai ^ 2 + aj ^ 2) = (ai - aj) * k

(ai ^ 2 - aj ^ 2)(ai ^ 2 + aj ^ 2) = ai * k - aj * k

ai ^ 4 - a ^ 4 = ai * k - aj * k

ai  ^ 4 - ai * k = aj ^ 4 - aj * k

在扫描时,把当前 ap ^ 4 % p - ap * k % p 存入桶,边存边统计就好了。

#include<bits/stdc++.h>
 using namespace std;
  typedef long long ll;
   typedef vector<ll> vl;
    typedef vector<int> vi;
     typedef pair<int,int> pii;
      typedef pair<int,ll> pil;
       typedef pair<ll,int> pli;
        typedef pair<ll,ll> pll;
  int main(){
    std::ios::sync_with_stdio(false);
          unordered_map<ll,ll> cc;
            ll n , p , k;
             ll ans = 0;
              cin >> n >> p >> k;
               for(int i = 0 ; i < n ; ++ i){
                    ll aa;cin >> aa;
                     ll t = ((aa % p) * (aa % p)) % p;
                      ll add = (t * t) % p - (k * aa) % p;
                      if(add < 0) add += p;
                       ans += cc[add];
                        cc[add]++;
               }
              cout << ans << endl;
       }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值