2013 成都赛区网赛 A Bit Fun

http://acm.hdu.edu.cn/showproblem.php?pid=4737

网络赛时,被暴力水过 了, 数据 有点弱吧,O(n^2)  10W的数据都过去了。。。。。。。

之后,寻找正解, 好像 二分+一些预处理  可做。。 不过这个时间比 暴力的时间还长。。。

据说还有什么双指针扫描。。的做法 

暴力 code :

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#include<vector>
using namespace std;
#define INF 100000000
int t,n,m;
int num[100005];
int main()
{
	//freopen("in.txt","r",stdin);
	int i,j,k;
	int time=0;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);
		for(i=1;i<=n;i++)
			scanf("%d",&num[i]);
		int tmp,cou=0;
		for(i=1;i<=n;i++)
		{
			tmp=num[i];
			if(tmp<m) cou++;
			else continue;
			for(j=i+1;j<=n;j++)
			{
				tmp=tmp|num[j];
				if(tmp<m) cou++;
				else break;
			}
		}
		printf("Case #%d: %d\n",++time,cou);
	}
	return 0;
}

二分的做法是 ,预处理 c[i][j]  (  从第一个数到第 j个数,中二进制第i位为1  的个数) 由于或运算 使值是单调递增(非递减的) 枚举i  (1到n)  二分上限 ,判断i 到mid 的数是否满足<m  详见代码

code 

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
#include<vector>
using namespace std;
#define INF 100000000
int t,n,m;
int num[100005],c[40][100005];
int test(int x,int mid)
{
	int i,j,k;
	int tmp=0;
	for(i=1;i<=30;i++)
	{
	    if(c[i][mid]-c[i][x-1]>0) tmp+=(1<<(i-1));
	}
	if(tmp<m) return 1;
	return 0;
}
int main()
{
	//freopen("in.txt","r",stdin);
	int i,j,k,time=0;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);
		for(i=1;i<=n;i++)
			scanf("%d",&num[i]);
		for(i=1;i<=30;i++) c[i][0]=0;
		for(i=1;i<=30;i++)
		{
			for(j=1;j<=n;j++)
			{
				int tmp=(num[j]>>(i-1))&1;
				c[i][j]=c[i][j-1]+tmp;
			}
		}
		int ans=0;
		for(i=1;i<=n;i++)
		{
			int le,ri,mid;
			le=i; ri=n;
			while(le<=ri)
			{
				mid=(le+ri)>>1;
				if(test(i,mid)) le=mid+1;
				else ri=mid-1;
			}
			ans+=(le-i);
		}
		printf("Case #%d: %d\n",++time,ans);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值