codeforces#572Div2 E---Count Pairs【数学】【同余】
题目:http://codeforces.com/contest/1189/problem/E
题意:给定$n$个互不相同数,一个$k$和一个质数$p$。问这$n$个数中有多少对数$(a_i+a_j)(a_i^2+a_j^2)\equiv k\,mod\,p$
思路:这一场的题目好像都很思维啊,代码量不多,想得出来就能写。
同余式左右两边同乘一个非零的数同余式不变,所以原式可以变为
$(a_i-a_j)(a_i+a_j)(a_i^2+a_j^2)\equiv (a_i-a_j)k = (a_i^2-a_j^2)(a_i^2+a_j^2)\equiv (a_i-a_j)k = (a_i^4-a_j^4)\equiv a_ik-a_jk = a_i^4 - a_ik \equiv a_j^4 - a_jk$
所以对于每一个数我们只需要计算$a_i^4-a_ik\,mod\,p$,然后根据这个能取到这个值的集合大小来计算答案就行了。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<map> 4 #include<set> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<cmath> 9 #include<stack> 10 #include<queue> 11 #include<iostream> 12 13 #define inf 0x3f3f3f3f 14 using namespace std; 15 typedef long long LL; 16 typedef pair<int, int> pr; 17 18 int n, p, k; 19 const int maxn = 3e5 + 5; 20 int num[maxn]; 21 map<int, int>mp; 22 23 int main() 24 { 25 scanf("%d%d%d", &n, &p, &k); 26 for(int i = 0; i < n; i++){ 27 scanf("%d", &num[i]); 28 int res = ((LL)num[i] * num[i] % p * num[i] % p - k) % p * num[i] % p; 29 res = (res + p) % p; 30 if(mp.find(res) != mp.end()){ 31 mp[res] = mp[res] + 1; 32 } 33 else{ 34 mp[res] = 1; 35 } 36 } 37 map<int, int>::iterator iter; 38 int ans = 0; 39 for(iter = mp.begin(); iter != mp.end(); iter++){ 40 int x = iter->second; 41 //cout<<iter->first<<":"<<iter->second<<endl; 42 ans += x * (x - 1) / 2; 43 } 44 printf("%d\n", ans); 45 return 0; 46 }