noip模拟赛?#16T3

题目大意:不告诉你QAQ

直接搬题解辣

对于位运算的题目,我们都可以把数拆成二进制,一位一位分开来考虑。那么我们只需要考虑0,1串的情况。我们枚举每一位作为连续段末端点R

对于or:如果这一位为0,那么我们需要找到前面最近的一个1,L在这之前的(L,R)的结果都是1,其它都是0,统计入答案;

如果这一位为1,那么所有的(L,R)结果都是1,直接计入答案。

对于and:如果这一位为0,结果都是0,答案直接不加。
如果这一位为1,我们找之前最近的0,L在这之后的(L,R)的结果为1,其它为0,统计入答案。

对于xor,我们需要知道之前xor完答案为0的(L,R-1)有几个,答案为1的(L,R-1)有几个,知道之后我们也可以统计答案。

而找最近的1,最近的0,以及之前xor完答案为0,1的有几个,这些我们可以在扫描过程中得到答案,所以做一遍是O(N),

我们做31遍即可得出每一位上的答案,就算出最终答案了。

注意:本题设定L>R也是有意义的,写的时候要注意这一点。

竟然不同调就A了(赛后QAQ)

爽!!!

#include<cstdio>
#include<cstring>
const int N=1e5+7;
int a[N];
int main()
{
	freopen("nine.in","r",stdin);
	freopen("nine.out","w",stdout);
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)	scanf("%d",&a[i]);
	long long sum1=0,sum2=0,sum3=0;
	int qu1=0,qu0=0;
	int ans1=0,ans0=0;
	for(int i=0;i<=30;i++)
	{
		int kkk=(1<<i);
		qu1=0,qu0=0;
		ans1=0,ans0=0;
		for(int r=1;r<=n;r++)
		{
			
			if(a[r]&kkk)
			{
				sum3+=(long long)kkk*(2*r-1);
				sum2+=(long long)kkk*(r*2-qu0*2-1);
				qu1=r;
				sum1+=(long long )kkk*ans0*2;
				sum1+=kkk;
				int tem0=ans0,tem1=ans1;
				ans0=tem1;
				ans1=tem0+1;
			}
			else 
			{
				sum3+=(long long )kkk*qu1*2;
				qu0=r;
				sum1+=(long long )kkk*ans1*2;
				int tem0=ans0,tem1=ans1;
				ans0=tem0+1;
				ans1=tem1;
			}
					
		}
	}
	long long ttt=(long long )n*n;
	printf("%.3f %.3f %.3f\n",sum1*1.0/ttt,sum2*1.0/ttt,sum3*1.0/ttt);
	fclose(stdin);
	fclose(stdout);
	
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值