2020年 1月3日 OJ习题【位运算&二进制枚举】

teacher Li

本题应考虑二进制异或,即对字符串的每一位进行异或,因为每个字符对应属于自己的ASICC码值,且根据题意,只有一位同学没来,也就说明,所有的字符串中,除了那个没来的同学,其他名字都出现了两遍,那样的话,从头到尾进行异或,最终得到的结果就会是没来的那位同学的名字

对于异或一个非常重要的性质,对于一个值异或同一个值两次,则结果还是原值。

一个数与0进行异或,其结果不变!!!

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int n,i,j,k;
	char x[30],y[30];
	k=1;
	while(cin>>n>>x)
	{
		for(i=1;i<=2*n-2;i++)
		{
			cin>>y;
			for(j=0;j<max(strlen(x),strlen(y));j++)//这里要取长的字符串长度//
			{
				x[j]=x[j]^y[j];
			}
		}
		printf("Scenario #%d\n",k++);
		printf("%s\n\n",x);
	}
	return 0;
} 

Find different

本题由于n非常大,无法用数组装,因此直接输入每一个数,然后直接进行异或,想法与上一题相同!!!

#include<bits/stdc++.h>
using namespace std;

int main()
{
	long long n;
	int ans,i;
	while(scanf("%lld",&n)!=EOF)
	{
		ans=0;
		for(long long j=0;j<n;j++)
		{
			scanf("%d",&i);
			ans=ans^i;
		}
		printf("%d\n",ans);
	}
	return 0;
} 

和为K–二进制枚举

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int n,flag,x[25];
	long long k,sum;
	while(cin>>n>>k)
	{
		flag=0;
		for(int i=0;i<25;i++)
		{
			x[i]=0;
		}
		for(int i=0;i<n;i++)
		{
			cin>>x[i];
		}
		for(int i=0;i<(1<<n);i++)
		{
			sum=0;
			for(int j=0;j<n;j++)
			{
				if(i&(1<<j))
				{
					sum+=x[j];
				}
			}
			if(k==sum)
			{
				flag=1;
				break;//找到一个符合就退出//
			}
		}
		if(flag==0)
			{
				cout<<"No"<<endl;
			}
		else
		{
			cout<<"Yes"<<endl;
		}
	} 
	return 0;
} 

陈老师加油-二进制枚举

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int t,sum,k1,k2,T;//t是临时变量,记录每种方案的油量//
	while(cin>>T)
	{
		sum=0;
		for(int i=0;i<(1<<15);i++)
		{
			k1=k2=0;
			t=T;
			for(int j=0;j<15;j++)
			{
				if(i&(1<<j))
				{
					t*=2;
					k1++;
				}
				else
				{
					t-=1;
					k2++;
					if(t<=0)//油不能不大于0//
					break;
				}
			}
			if(k1==5&&k2==10&&t==0)
			{
				sum++;
			}
		}
		cout<<sum<<endl;
	}
	return 0;
} 

纸牌游戏-二进制-搜索

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int n,p;
	int x[25],sum,count;
	while(cin>>n>>p)
	{
		for(int i=0;i<n;i++)
		{
			x[i]=0;
		}
		for(int i=0;i<n;i++)
		cin>>x[i];
		count=0;
		for(int i=0;i<(1<<n);i++)
		{
			sum=0;
			for(int j=0;j<n;j++)
			{
				if(i&(1<<j))
				{
					sum+=x[j];
				}
			}
			if(sum==p)
				count++;
		}
		cout<<count<<endl;
	}
	return 0;
} 

权利指数

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int t,n,sum,add;//sum是总票数,add是同意的票数//
	int x[25],y[25];//x是票数数组,y是权利指数数组//
	while(cin>>t)
	{
		for(int i=0;i<t;i++)
		{
			sum=0;
			cin>>n;
			for(int i=0;i<n;i++)
				x[i]=y[i]=0;
			for(int i=0;i<n;i++)
			{
				cin>>x[i];
				sum+=x[i];
			}
			for(int i=0;i<(1<<n);i++)
			{
				add=0;
				for(int j=0;j<n;j++)
				{
					if(i&(1<<j))
					{
						add+=x[j];
					}
				}
				if(add>(sum/2))
				{
					for(int j=0;j<n;j++)
					{
						if(i&(1<<j))
						{
							add-=x[j];
							if(add<=(sum/2))//无论该团体是不是关键小团体,都得把剪掉的数再加回来//
								{
									y[j]++;
									add+=x[j];
								}
							else
							{
								add+=x[j];
							}
						}
					}
				}
			}
			for(int i=0;i<n-1;i++)
				cout<<y[i]<<" ";
				cout<<y[n-1]<<endl;
		}
	}
	return 0;
} 

趣味解题

本题的想法是先把每道题的ac,wa的概率都算出来,分别装到两个数组里,然后二进制枚举进行遍历,对于每种方案的概率是ac题的概率之积乘以wa题的概率之积,然后把所有ac题数符合题意的方案的概率相加

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int t,n,x,k;
	double a[15],b[15],c[15],ac[15],wa[15],ans,ans1;
	while(scanf("%d",&t)!=EOF)
	{
		for(int i=0;i<t;i++)
		{
			scanf("%d",&n);
		for(int i=0;i<n;i++)
		{
			scanf("%lf",&a[i]);
		}	
		for(int i=0;i<n;i++)
		{
			scanf("%lf",&b[i]);
		}
		for(int i=0;i<n;i++)
		{
			scanf("%lf",&c[i]);
		}
		scanf("%d",&x);
		for(int i=0;i<n;i++)
		{
			wa[i]=(1.0-a[i])*(1.0-b[i])*(1.0-c[i]);
			ac[i]=1.0-wa[i];
		}
		ans=0;
		for(int i=0;i<(1<<n);i++)
		{
			k=0;
			ans1=1.0;
			for(int j=0;j<n;j++)
			{
				if(i&(1<<j))
				{
					ans1*=ac[j];
					k++;
				}
				else
				{
					ans1*=wa[j];
				}
			}
			if(k==x)
			{
				ans+=ans1;
			}
		}
		printf("%.4lf\n",ans);
		}
	} 
	return 0;
} 

四糸乃买花-二进制枚举

#include <bits/stdc++.h>
using namespace std;

int main()
{
	int n,k,count;
	long long a[25],w,w1;//w1记录每种方案剩下的钱// 
	cin>>n;
	for(int i=0;i<n;i++)
	cin>>a[i];
	cin>>w;
	count=0;
	for(int i=0;i<(1<<n);i++)
	{
		k=0;
		w1=w;
		for(int j=0;j<n;j++)
		{
			if(i&(1<<j))
			{
				w1-=a[j];
				k++;
			}
		}
		if(k%4==0&&w1%4==0&&k>0&&k<n&&w1>=0)//k不能为0,也不能为n,而且剩下的钱应为正或者正好为0,且k,w1都要是4的倍数// 
		{
			count++;
		}
	}
	cout<<count<<endl;
	return 0;
}

发布了10 篇原创文章 · 获赞 1 · 访问量 144

猜你喜欢

转载自blog.csdn.net/shiroi2333/article/details/103821134