其他分享
首页 > 其他分享> > 2022牛客多校4 N Particle Arts

2022牛客多校4 N Particle Arts

作者:互联网

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

题意:

给\(n\)个数,每次任选两个数\(a,b\),变成两个新数\(a|b\)和\(a\&b\),在进行若干次操作后,数列会处于稳定,求方差

解法:

观察操作我们会发现,在操作前后,每一位上的1的数量不会发生变化,如果有两个1,与和或产生的都是1,如果有一个1,只有与是1,如果没有1,结果也没有1,所以两个数的和也不会发生变化。

继续观察操作我们会发现,1会尽可能地向一个方向靠拢,也就是说,尽可能让其中一个数每一位都是1,另一个数拿剩下的1,那么不论进行多少次操作,这种特性依然存在

所以最终就是先求出每一位1出现的次数,然后构造新的数列,新的数列是非严格递减的,如果某一位还有剩余的1就尽可能往前放。

这道题有个易错点就是用long long需要注意优化分数运算,很容易爆掉,我就改了好久,最后换成int128了

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cctype>
#define ll long long
#define gc getchar
#define maxn 100005
#define maxm 20
using namespace std;

inline ll read(){
	ll a=0;int f=0;char p=gc();
	while(!isdigit(p)){f|=p=='-';p=gc();}
	while(isdigit(p)){a=(a<<3)+(a<<1)+(p^48);p=gc();}
	return f?-a:a;
}int n;
ll a[maxn],b[maxm];
__int128 sum;

__int128 gcd(__int128 a,__int128 b){
	return a%b==0?b:gcd(b,a%b);
}

struct ahaha{
	__int128 a,b;
	inline void merge(){
		__int128 c=gcd(a,b);
		a/=c,b/=c;
	}
	inline ahaha friend operator+(const ahaha x,const ahaha y){
		ahaha c;
		__int128 zz=gcd(x.b,y.b);
		c.b=x.b/zz*y.b;
		c.a=y.b/zz*x.a+x.b/zz*y.a;
		c.merge();
		return c;
	}
}u,ans;

inline void chuli(int p){
	for(int i=15;~i;--i)
		if((1<<i)&p){
			++b[i];
			sum+=1<<i;
		}
}

void print(__int128 x){
	if(x>9)print(x/10);
	putchar(x%10+'0');
}

int main(){
	n=read();ans.b=1;
	for(int i=1;i<=n;++i){
		a[i]=read();
		chuli(a[i]);
	}
	u.a=sum,u.b=n;
	u.merge();
	for(int i=1;i<=n;++i){
		a[i]=0;
		for(int j=15;~j;--j)
			if(b[j]){
				a[i]+=1<<j;
				--b[j];
			}
		ahaha zz;
		zz.a=a[i]*u.b-u.a;
		zz.b=u.b;
		zz.merge();
		zz.a*=zz.a;
		zz.b*=zz.b;
		zz.merge();
		ans=ans+zz;
		ans.merge();
	}
	ll p=gcd(ans.a,n);
	ans.a/=p;n/=p;
	ans.b*=n;
	ans.merge();
	print(ans.a);
	putchar('/');
	print(ans.b);
	return 0;
}

标签:Arts,Particle,int,ll,long,牛客,gc,include,define
来源: https://www.cnblogs.com/hanruyun/p/16541682.html