AGC 047 C 题解
一个数论好题
可以发现P是一个NTT模数,原根是2。
则任何一个<P的数都可以表示成(2^xmod p)。
两个数相乘也就可以表示成(2^x imes 2^y=2^{(x+y)mod (p-1)})
直接fft就好了。
/*
{
######################
# Author #
# Gary #
# 2021 #
######################
*/
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
//inline int read(){
// int x=0;
// char ch=getchar();
// while(ch<'0'||ch>'9'){
// ch=getchar();
// }
// while(ch>='0'&&ch<='9'){
// x=(x<<1)+(x<<3)+(ch^48);
// ch=getchar();
// }
// return x;
//}
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
typedef complex<double> Comp;
const double PI=3.14159265358979323846;
const Comp I(0,1);
const int len=1<<19;
int rev[len];
void butterfly(vector<Comp> & v){
rep(i,len){
rev[i]=rev[i>>1]>>1;
if(i&1) rev[i]|=len>>1;
}
rep(i,len) if(rev[i]>i) swap(v[i],v[rev[i]]);
}
vector<Comp> fft(vector<Comp> v,int ty){
butterfly(v);
vector<Comp> nex;
for(int l=2;l<=len;l<<=1){
nex.clear();
nex.resize(len);
Comp step(cos(2.0*PI/l),sin(2.0*ty*PI/l));
for(int j=0;j<len;j+=l){
Comp now(1,0);
for(int k=0;k<l/2;++k){
Comp A,B;
A=v[j+k];
B=v[j+l/2+k];
B=now*B;
nex[j+k]=A+B;
nex[j+k+l/2]=A-B;
now=now*step;
}
}
v=nex;
}
return v;
}
const int MOD=200003;
const int g=2;
int is[MOD],pow_[MOD];
vector<Comp> v(len);
LL cnt[len];
int main(){
int now=1;
rb(i,0,MOD-2){
is[now]=i;
pow_[i]=now;
now<<=1;
now%=MOD;
}
vector<int> a;
LL rest=0;
int n;
scanf("%d",&n);
rb(i,1,n){
int ai;
scanf("%d",&ai);
if(ai){
a.PB(ai);
cnt[is[ai]]++;
}
}
n=a.size();
rep(i,len) v[i]=Comp(cnt[i],0);
v=fft(v,1);
rep(i,len) v[i]*=v[i];
v=fft(v,-1);
rep(i,len) cnt[i]=floor((v[i].real()/len)+0.5);
rb(i,0,MOD-2){
cnt[i]+=cnt[i+MOD-1];
rest+=1ll*pow_[i]*cnt[i];
}
rep(i,n)
rest-=1ll*a[i]*a[i]%MOD;
cout<<rest/2<<endl;
return 0;
}