题意:
给你n个数,问你有多少对i,j,满足i<j,并且1/(ai+aj)=1/ai+1/aj 在%p意义下。
题解:
不愧是高中生,推公式神题。
将式子通分化简后可得(ai2+aj2+ai*aj)%p=0。
然后两边同时将两边乘(ai-aj),化简可得(ai3-aj3)%p=0。
然后就可以用map记录一下个数,并且减掉ai==aj时不合法的情况就行了。
1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=(a);i<=(b);++i) 3 using namespace std; 4 typedef long long ll; 5 6 const int N=1e5+7; 7 int t,n; 8 ll p,a[N]; 9 map<ll,int>hsh; 10 map<ll,int>cnt; 11 12 ll mul(ll a,ll b) 13 { 14 ll an=0; 15 while(b) 16 { 17 if(b&1)an=(an+a)%p; 18 b>>=1,a=(a+a)%p; 19 } 20 return an; 21 } 22 23 int main() 24 { 25 scanf("%d",&t); 26 while(t--) 27 { 28 scanf("%d%lld",&n,&p); 29 hsh.clear(); 30 cnt.clear(); 31 ll ans=0; 32 F(i,1,n) 33 { 34 scanf("%lld",a+i); 35 if(!a[i])continue; 36 if(mul(mul(a[i],a[i]),3))ans-=cnt[a[i]]; 37 ll tp=mul(mul(a[i],a[i]),a[i]); 38 ans+=hsh[tp]++; 39 ++cnt[a[i]]; 40 } 41 printf("%lld ",ans); 42 } 43 return 0; 44 }