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<<' ';
}
}

浙公网安备 33010602011771号