题目链接:http://codeforces.com/contest/1189/problem/E
题意:现在有 n n n个数,你需要找出有多少对 ( i , j ) (i,j) (i,j)满足 ( a i + a j ) ∗ ( a i 2 + a j 2 ) % p = k (a_{i}+a_{j})*(a_{i}^{2}+a_{j}^{2})\%p=k (ai+aj)∗(ai2+aj2)%p=k。
解题心得:
- 刚开始看到这个题除了暴力没啥思路,但是 n n n的范围是 3 e 5 3e5 3e5,暴力是 n 2 n^{2} n2的复杂度啊。
- 但是 ( a i + a j ) ∗ ( a i 2 + a j 2 ) (a_{i}+a_{j})*(a_{i}^{2}+a_{j}^{2}) (ai+aj)∗(ai2+aj2)这个公式真的是太熟悉了,情不自禁就想给它加个 ( a i − a j ) (a_{i}-a_{j}) (ai−aj),这样等式两边就变成了 ( a i − a j ) ∗ ( a i + a j ) ∗ ( a i 2 + a j 2 ) % p = k ∗ ( a i − a j ) % p (a_{i}-a_{j})*(a_{i}+a_{j})*(a_{i}^{2}+a_{j}^{2})\%p=k*(a_{i}-a_{j})\%p (ai−aj)∗(ai+aj)∗(ai2+aj2)%p=k∗(ai−aj)%p再给它变一下就成了 ( a i 4 − a j 4 ) % p = ( k ∗ a i + k ∗ a j ) % p (a_{i}^{4}-a_{j}^{4})\%p=(k*a_{i}+k*a_{j})\%p (ai4−aj4)%p=(k∗ai+k∗aj)%p再移项就变成了 ( a i 4 − k ∗ a i ) % p = ( a j 4 − k ∗ a j ) % p (a_{i}^{4}-k*a_{i})\%p=(a_{j}^{4}-k*a_{j})\%p (ai4−k∗ai)%p=(aj4−k∗aj)%p这样问题变成了 O { n } O\{n\} O{n}统计 a i 4 − k ∗ a i a_{i}^{4}-k*a_{i} ai4−k∗ai值的个数,将值相等的两两组合一下答案就出来了。
#include <bits/stdc++.h>
using namespace std;
typedef complex<double> cp;
typedef long long ll;
const ll maxn = 3e5+100;
const double pi = acos(-1);
ll n, num[maxn], p, k;
map <ll, ll> maps;
void init() {
scanf("%lld%lld%lld", &n, &p, &k);
for(int i=1;i<=n;i++) scanf("%lld", &num[i]);
}
int main() {
// freopen("1.in.txt", "r", stdin);
init();
for(int i=1;i<=n;i++) {
ll ai4 = num[i] * num[i] % p *num[i] %p *num[i] % p;
ll kai = k * num[i] %p;
if(ai4 < kai) ai4 += p;
maps[ai4-kai]++;
}
map <ll, ll> :: iterator iter;
ll ans = 0;
for(iter=maps.begin();iter!=maps.end();iter++) {
ll cnt = iter->second;
ans += cnt*(cnt-1)/2;
}
printf("%lld\n", ans);
return 0;
}