Codeforces Round #572 (Div. 1)B. Count Pairs【組合數學】

題目鏈接:https://codeforc.es/problemset/problem/1188/B

題目大意:給定n,p,k,(p)n,p,k,(p爲素數)和長度爲nn的數組aa,問滿足1<=i,j<=n1<=i,j<=n中,(ai+aj)(ai2+aj2)=k(mod k)(a_i+a_j)*(a_i^2+a_j^2)=k (mod\ k)的對數。

思路:

(ai+aj)(ai2+aj2)=k(mod k)(a_i+a_j)*(a_i^2+a_j^2)=k (mod\ k)

(ai+aj)(aiaj)(ai2+aj2)=k(aiaj)(mod k)(a_i+a_j)*(a_i-a_j)*(a_i^2+a_j^2)=k*(a_i-a_j) (mod\ k)

(ai2aj2)(ai2+aj2)=k(aiaj)(mod k)(a_i^2-a_j^2)*(a_i^2+a_j^2)=k*(a_i-a_j) (mod\ k)

ai4kai=aj4kaj(mod k)a_i^4-k*a_i=a_j^4-k*a_j (mod\ k)

那麼此時問題轉換成組合數學的問題:先求出{ai4kai(mod k)}\{a_i^4-k*a_i (mod\ k)\}對應出現的次數cntcnt,那麼:這個數對答案的貢獻則爲Ccnt2C_{cnt}^2,用setset去重一下就okok了。

AC代碼:

#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+100;
typedef long long ll;
ll qpow(ll x,ll y,ll mo){
    ll ans=1;
    while(y>0){
        if(y&1){
            ans=ans*x%mo;
        }
        x=x*x%mo;
        y>>=1;
    }
    return ans;
}
ll a[maxn];
map<ll ,ll >mp;
set<ll>se;
int main()
{
    ll n,p,k;
    cin>>n>>p>>k;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    for(int i=1;i<=n;i++){
        ll ans=(qpow(a[i],4,p)-k*a[i]%p+p)%p;
        mp[ans]++;
        se.insert(ans);
    }
    ll sum=0;
    for(auto it:se){
        ll tmp=mp[it];
        sum+=tmp*(tmp-1)/2;
    }
    cout<<sum<<endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章