HDU 6128 Inverse of sum(数论)——2017 Multi-University Training Contest - Team 7

传送门

Inverse of sum

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 326    Accepted Submission(s): 112


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

题目大意:

1009

n 个小于质数 p 的非负整数 a1n ,你想知道有多少对 i,j(1i<jn) ,使得模 p 意义下 1ai+aj1ai+1aj ,即这两数的和的逆元等于它们逆元的和,注意零元没有逆元。 1n105,2p1018

解题思路:

1ai+aj1ai+1aj

将式子进行通分得到:
(ai+aj)2=aiaj

将式子展开并移项,进行合并同类项得到:
a2i+aiaj+a2j0modp

将式子两边同时乘以 aiaj 得到:
a3ia3j0modp

推到这儿就会发现已经很好做了,就是用一个 map 统计一下每个数 x3modp 的个数,然后就是从 x3modp 结果相同的数中选两个数(题目要求就是两个数)。
还需要注意的几个点:
1) 0没有逆元
2) 当 aiaj=0 的时候不满足条件,需要特判 就用另一个 map 存一下相同的个数,然后减去其中对应的方案数就OK了
3) 当模数是 3 的时候 需要特殊判断,这个就不需要考虑两个数相同的情况了,因为 3 没有二次剩余

代码:

#include 
using namespace std;
typedef long long LL;
const int MAXN = 1e5+5;
const double PI = acos(-1);
const double eps = 1e-8;
const LL MOD = 1e9+7;
inline int GCD(int a, int b){
    if(b  == 0) return a;
    return GCD(b, a%b);
}
inline LL GCD(LL a, LL b){
    if(b  == 0) return a;
    return GCD(b, a%b);
}
inline int LCM(int a, int b){
    return a/GCD(b, a%b)*b;
}
inline LL LCM(LL a, LL b){
    return a/GCD(b, a%b)*b;
}
namespace IO {
    const int MX = 4e7; //1e7占用内存11000kb
    char buf[MX]; int c, sz;
    void begin() {
        c = 0;
        sz = fread(buf, 1, MX, stdin);
    }
    inline bool read(LL &t) {
        while(c < sz && buf[c] != '-' && (buf[c] < '0' || buf[c] > '9')) c++;
        if(c >= sz) return false;
        bool flag = 0; if(buf[c] == '-') flag = 1, c++;
        for(t = 0; c < sz && '0' <= buf[c] && buf[c] <= '9'; c++) t = t * 10 + buf[c] - '0';
        if(flag) t = -t;
        return true;
    }
}
LL Multi(LL a, LL b, LL p){
    LL ans = 0;
    while(b){
        if(b & 1) ans = (ans + a) % p;
        b>>=1;
        a = (a + a) % p;
    }
    return ans;
}
LL Pow(LL a, LL b, LL p){
    LL ans = 1;
    while(b){
        if(b & 1) ans = Multi(ans, a, p);
        b>>=1;
        a = Multi(a, a, p);
    }
    return ans;
}
void Exgcd(LL a, LL b, LL &x, LL &y){
    if(b == 0){
        x = 1;
        y = 0;
        return ;
    }
    LL x1, y1;
    Exgcd(b, a%b, x1, y1);
    x = y1;
    y = x1 - (a/b)*y1;
}
mapint>mp, mp1;
mapint>::iterator it;
int main(){
    //freopen("C:/Users/yaonie/Desktop/in.txt", "r", stdin);
    //freopen("C:/Users/yaonie/Desktop/out.txt", "w", stdout);
    IO::begin();
    LL T; //scanf("%d", &T);
    IO::read(T);
    while(T--){
        LL n; //scanf("%d", &n);
        IO::read(n);
        LL p, x; //scanf("%lld", &p);
        IO::read(p);
        mp.clear();
        mp1.clear();
        for(int i=0; i//scanf("%lld",&x);
            IO::read(x);
            if(x == 0) continue;
            mp1[x]++;
            x = Pow(x, 3, p);
            mp[x]++;
        }
        LL ans = 0;
        for(it=mp.begin(); it!=mp.end(); it++){
            LL tmp = (it->second);
            tmp = tmp*(tmp-1)/2;
            ans = ans + tmp;
        }
        if(p != 3)
        for(it=mp1.begin(); it!=mp1.end(); it++){
            LL tmp = (it->second);
            tmp = tmp*(tmp-1)/2;
            ans = ans - tmp;
        }
        printf("%lld\n",ans);
    }
    return 0;
}
/**
                   _ooOoo_
                  o8888888o
                  88" . "88
                  (| -_- |)
                  O\  =  /O
               ____/`---'\____
             .'  \\|     |//  `.
            /  \\|||  :  |||//  \
           /  _||||| -:- |||||-  \
           |   | \\\  -  /// |   |
           | \_|  ''\---/''  |   |
           \  .-\__  `-`  ___/-. /
         ___`. .'  /--.--\  `. . __
      ."" '<  `.___\_<|>_/___.'  >'"".
     | | :  `- \`.;`\ _ /`;.`/ - ` : | |
     \  \ `-.   \_ __\ /__ _/   .-` /  /
======`-.____`-.___\_____/___.-`____.-'======
                   `=---='
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
         佛祖保佑       每次AC
**/

你可能感兴趣的:(ACM_数论,ACM_HDU,Multi,ITAK的ACM之路)