Problem Description
There are
n
nonnegative integers
a1…n
which are less than
p
. HazelFan wants to know how many pairs
i,j(1≤i<j≤n)
are there, satisfying
1ai+aj≡1ai+1aj
when we calculate module
p
, which means the inverse element of their sum equals the sum of their inverse elements. Notice that zero element has no inverse element.
Input
The first line contains a positive integer
T(1≤T≤5)
, denoting the number of test cases.
For each test case:
The first line contains two positive integers n,p(1≤n≤105,2≤p≤1018) , and it is guaranteed that p is a prime number.
The second line contains n nonnegative integers a1...n(0≤ai<p) .
For each test case:
The first line contains two positive integers n,p(1≤n≤105,2≤p≤1018) , and it is guaranteed that p is a prime number.
The second line contains n nonnegative integers a1...n(0≤ai<p) .
Output
For each test case:
A single line contains a nonnegative integer, denoting the answer.
A single line contains a nonnegative integer, denoting the answer.
Sample Input
2 5 7 1 2 3 4 5 6 7 1 2 3 4 5 6
Sample Output
4 6这个题题意是求使得 (ai+aj) 在模 p 下的逆元等于 ai 在模 p 下的逆元加上 aj 在模 p 下的逆元的 i j 的对数( i<j )式子两边同乘( ai + aj )*ai*aj 得 ai*aj=ai*(ai+aj)+aj*(ai+aj) (mod p).化简: ai*aj=ai^2 + aj^2 + 2*ai*aj (mod p)0=ai^2 + aj^2 + ai*aj (mod p)这个时候就可以用二次剩余搞了,但是我实在太弱,不会二次剩余,详情请百度大佬的做法但是还有另外一个神奇的算法:两边同乘 (ai-aj)然后就变成了:0=ai^3-aj^3 (mod p)令 bi=ai^3 (mod p), 找多少对 bi==bj然后就好说了不过要注意几点:①ai=0时是没有逆元的直接continue②当 ai==aj 时,会有ai-aj=0,所以在乘以 ai-aj 之前要判断 ai^2+aj^2+ai*aj 是否等于0,不等于0的话你乘了 ai-aj 也没用③p=3 时要单独特判,因为 p=3 时 ai 无非就等于 0 1 2 这三个,其中 0 直接continue,aj=ai时它们不管等于1还是2,ai^2+aj^2+ai*aj 模 p 都等于0,ai不等于aj时不管怎样目标式子模p都不等于0,与p取其他值的情况略有不同 ④这个方法并不优,只是好写而已,所以写法一定要优美,能省的计算就省,不然会TLE,我用不怎么优美的同一段代码交了几次才AC了两三次, 2800ms,2900ms这样子,其他的都T了 ⑤在计算 ai*aj 的时候因为结果会炸 long long 所以要用快速乘法 代码:#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <vector> #include <queue> #include <stack> #include <cstdlib> #include <cmath> #include <map> #include <string> using namespace std; typedef long long LL; const int MOD=1e9+7; map<LL,LL>s,t; LL n,p; LL mul(LL a,LL b) { LL ans=0; a=a%p; b=b%p; while(b>0) { if(b&1) ans=(ans+a)%p; a=(a+a)%p; b>>=1; } return ans; } LL a[200000+3]; LL b[200000+3]; LL c[200000+3]; int main() { int T; scanf("%d",&T); while(T--) { s.clear(); t.clear(); scanf("%lld%lld",&n,&p); if(p==3) { LL a1=0,a2=0,a3=0; for(int i=0;i<n;i++) { LL x; scanf("%lld",&x); if(x==1)a1++; else if(x==2)a2++; } printf("%lld\n",a1*(a1-1)/2+a2*(a2-1)/2); continue; } for(int i=0;i<n;i++) { scanf("%lld",&a[i]); if(a[i]==0)continue; LL y=mul(a[i],a[i]); LL z=mul(a[i],y);//ai==aj时ai^2 + aj^2 + ai*aj就成了 3 * ai^2 嘛 b[i]=z; c[i]=mul(3,y); s[z]++; t[a[i]]++; } /* for(int i=0;i<n;i++) { scanf("%lld",&a[i]); if(a[i]==0)continue; LL z=mul(a[i],mul(a[i],a[i])); b[i]=z; c[i]=mul(3,mul(a[i],a[i])); s[z]++; t[a[i]]++; } 之前交了好几发的同一段代码用的是这个,同一个快速乘算了两次,导致交几发才玄学过一发,其他的都T了,有兴趣的可以玩一下 */ LL ans=0; for(int i=0;i<n;i++) { if(a[i]==0)continue; { LL z=0; if(c[i]==0)//ai==aj时判断ai^2 + aj^2 + ai*aj为等于0的话不用减掉ai==aj的情况,直接算ai^3==aj^3即可 { z=s[b[i]]-1;//减掉ai它自己 } else//ai==aj时判断ai^2 + aj^2 + ai*aj为不等于0的话要减掉ai==aj的情况再算ai^3==aj^3 { z=s[b[i]]-t[a[i]]; } ans+=z; } } ans/=2; printf("%lld\n",ans); } return 0; }
emmmm........大概就这样了
本人蒟蒻,如有错误,还望指正