kmjp's blog

競技プログラミング参加記です

yukicoder : No.2651 [Cherry 6th Tune B] Complex комбинат

これが一番しんどかった。
https://yukicoder.me/problems/no/2651

問題

N要素の複素数列Zが与えられる。
2要素の対(Z_i, Z_j)に対し、|Z_i/Z_j-Z_j/Z_i|^2の総和を求めよ。

解法

絶対値の二乗を、複素数のその共役複素数の積と言い換えて式変形すると
 \displaystyle \left(\sum_i |z_i|^2\right) \left(\sum_i \frac{1}{|z_i|^2}\right) - Re \left\lbrack \sum_i  {\beta}_i \sum_i \frac{1}{{\beta}_i}\right\rbrack
となる。
あとは各Sumの部分を計算しよう。

int T;
int N;
ll X[302020],Y[302020],R[302020],RR[302020];

const ll mo=998244353;
ll modpow(ll a, ll n = mo-2) {
	ll r=1;a%=mo;
	while(n) r=r*((n%2)?a:1)%mo,a=a*a%mo,n>>=1;
	return r;
}


void solve() {
	int i,j,k,l,r,x,y; string s;
	
	cin>>T;
	while(T--) {
		cin>>N;
		
		ll RS=0;
		ll RRS=0;
		ll BIS=0,BRS=0,RBIS=0,RBRS=0;
		FOR(i,N) {
			cin>>X[i]>>Y[i];
			R[i]=X[i]*X[i]+Y[i]*Y[i];
			RR[i]=modpow(R[i]);
			(RS+=R[i])%=mo;
			(RRS+=RR[i])%=mo;
			
			(BIS+=(mo+X[i]*X[i]-Y[i]*Y[i])*RR[i])%=mo;
			(BRS+=(mo+2*X[i]*Y[i])*RR[i])%=mo;
			(RBIS+=(mo+X[i]*X[i]-Y[i]*Y[i])*RR[i])%=mo;
			(RBRS+=(mo-2*X[i]*Y[i])*RR[i])%=mo;
		}
		
		ll ret=RS*RRS%mo-(BIS*RBIS-BRS*RBRS);
		
		
		
		cout<<(ret%mo+mo)%mo<<endl;
	}
}

まとめ

競技プログラミングで複素数余り使わないので、いろいろ忘れるな…。