HDU 6128(乱搞)

Problem Description
There are n nonnegative integers a1n which are less than p. HazelFan wants to know how many pairs i,j(1i<jn) are there, satisfying 1ai+aj1ai+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(1T5), denoting the number of test cases.
For each test case:
The first line contains two positive integers n,p(1n105,2p1018), and it is guaranteed that p is a prime number.
The second line contains n nonnegative integers a1...n(0ai<p).
 

Output
For each test case:
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
式子两边同乘( 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 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long LL;
const int MOD=1e9+7;
maps,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

 
emmmm........大概就这样了
本人蒟蒻,如有错误,还望指正


HDU 6128(乱搞)_第1张图片




你可能感兴趣的:(基础数论)