2023 牛客寒假算法基础集训营 2L Tokitsukaze and Three Integers

\(\texttt{Description}\)

题目传送门

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

    • \(i\ne j,j\ne k,k\ne i\).

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

  • \(1\le n,p\le 5000\)\(0\le n\le 10^9\).

\(\texttt{Solution}\)

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

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

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

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

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

\(\texttt{Code}\)

$\texttt{Click Here}$
#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<<' ';
    }
}

测评链接

posted @ 2023-01-29 21:43  lzyqwq  阅读(46)  评论(0)    收藏  举报