题解 | #N Particle Arts#

Particle Arts

https://ac.nowcoder.com/acm/contest/33189/N

N Particle Arts

无限碰撞之后,每一位的1和0都会分成两边,此时任意两个数字碰撞都会有 [ab=a,a&b=b](ab)[a|b=a,a\&b=b](a \ge b) 。(证明请找出题人)

重构一下数组,也就是按顺序把每一位的1尽可能丢进一个数字里,那么可以保证,先得到的数字跟后得到的数字之间一定可以满足 [ab=a,a&b=b](ab)[a|b=a,a\&b=b](a \geq b)

例如,样例中,{1,2,3,4,5}转成2进制即{001,010,011,100,101},重构后为{111,111,001,000,000},任意两个数字碰撞都将不再改变数组。

之后计算这个数组的方差,可以把式子展开,就只需要整数计算,可以直接开long long存,最后再gcd一下即可。

sum=1naisum = \sum_1^n a_i

μ=sumn\mu = \frac{sum}{n}

(xiμ)2=xi22xiμ+μ2(x_i - \mu)^2 = x_i^2 - 2 x_i \mu + \mu ^2 (完全平方公式展开)

ab=1nxi2+n×sum2n21n2×xi×sumn\frac{a}{b} = \sum_1^n x_i^2 + n \times \frac{sum^2}{n^2} - \sum_1^n 2 \times x_i \times \frac{sum}{n}

a=1nn×xi2+sum21n2×xi×suma=\sum_1^n n \times x_i^2 +sum^2 - \sum_1^n 2 \times x_i \times sum (对 xi2x_i^2 部分通分)

b=nb=n

σ2=ab×1n \sigma^2 = \frac{a}{b} \times \frac{1}{n}

此时,所有计算都为整数计算,并且在long long范围内,最后对 aan2n^2 约分即可。

#include<bits/stdc++.h>

using namespace std;

using LL = long long;

void solve(){
	LL n;
	cin>>n;
	vector<LL> a(n+1);
	vector<int> b(20);
	for(int i=1;i<=n;i++){
		cin>>a[i];
		for(int j=0;j<20;j++){
			if(a[i]&(1<<j)) b[j]++;
		}
	}
	LL sum=0;
	for(int i=1;i<=n;i++){
		a[i]=0;
		for(int j=0;j<20;j++){
			if(b[j]){
				b[j]--;
				a[i]+=1<<j;
			}
		}
		sum+=a[i];
	}
	LL ans=0,sub=0;
	for(int i=1;i<=n;i++){
		ans+=a[i]*a[i];
		sub+=a[i]*sum;
	}
	ans*=n;
	ans+=sum*sum;
	ans-=2*sub;
	if(ans==0){
		cout<<"0/1"<<endl;
		return;
	}
    n*=n;
	int g=gcd(ans,n);
	ans/=g;
	n/=g;
	cout<<ans<<"/"<<n<<endl;
}

int main(){
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	solve();
	return 0;
}
/*
*/

全部评论

相关推荐

7 收藏 评论
分享
牛客网
牛客企业服务