更好的阅读体验

题目传送门

  • 给定 a1ana_1\sim a_n,求当 x[1,p)x\in[1,p) 时满足以下条件的有序三元组 (i,j,k)(i,j,k) 的数量:

    • ij,jk,kii\ne j,j\ne k,k\ne i.

    • (aiaj+ak)modp=x(a_i\cdot a_j+a_k) \bmod p=x.

  • 1n,p50001\le n,p\le 50000n1090\le n\le 10^9.

Solution\texttt{Solution}

分别求 x=1p1x=1\sim p-1 时的答案 ansx\operatorname{ans}_x.对于枚举的每一个 xx,枚举 k=1nk=1\sim n,这样可以得到 aiajmodp=(xak)modpa_i\cdot a_j \bmod p=(x-a_k)\bmod p.

考虑预处理 vw(w[1,p))v_w(w\in[1,p)) 表示满足 aiajmodp=wa_i\cdot a_j\bmod p=w有序对 (i,j)(ij)(i,j)(i\ne j) 的个数. 这个可以枚举两个数,然后将它们乘积的余数对应的 vv+1+1. 这样对于枚举的 kk,直接将 ansx\operatorname{ans}_x 加上 v(xak)modpv_{(x-a_k)\bmod p} 即可.

不过 v(xak)modpv_{(x-a_k)\bmod p} 可能计算了 aka_k 去乘上某个数,因此还要预处理 ui,j(i[1,n],j[1,p))u_{i,j}(i\in[1,n],j\in[1,p)),表示满足 aiatmodp=j(ti,t[1,n])a_i\cdot a_t\bmod p=j(t\ne i,t\in[1,n])tt 的个数. 这个可以枚举 i,ti,t 两个数,然后然后将它们乘积的余数对应的 uiu_i+1+1.

最后再把 ansx\operatorname{ans}_x 减去 2uk,x2\cdot u_{k,x} 即可. 注意是 22 倍,因为 vv 的值是有序对个数,当 i=k,j=ki=k,j=k 时都要减去 uk,xu_{k,x}.

时间复杂度为 O(n2+np)\mathcal{O}(n^2+np),空间复杂度为 O(np+n+p)\mathcal{O}(np+n+p),可以接受.

Code\texttt{Code}

点击查看代码
#include<bits/stdc++.h>
#define int long long//相乘会见祖宗.
#define N 5001
using namespace std;
int u[N][N],v[N],p,n,a[N];
signed main(){
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(0);
    cin>>n>>p;
    for(int i=1;i<=n;++i){
        cin>>a[i];
    }
    for(int i=1;i<=n;++i){
        for(int j=1;j<=n;++j){
            if(i^j){
                ++v[a[i]*a[j]%p];
                ++u[i][a[i]*a[j]%p];
            }
        }
    }
    for(int i=0,k;i<p;++i){
        k=0;
        for(int j=1,q;j<=n;++j){
            q=(i-a[j]+p*1145141919810)%p;//注意负数取模.
            k+=v[q]-u[j][q]*2;
        }
        cout<<k<<' ';
    }
}

测评链接