2020年1月3日 位运算与二进制枚举
林大OJ 643 teacher Li
字符串异或问题,思路就是把所有字符串的每个字符依次异或,字符对应得ASCII码也是一个数字,所以字符也可以去异或。
而且在二进制中,0与任何数异或都等于那个数本身。
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,i,j,k;
k=0;
while(~scanf("%d",&n)){
char a[40],b[40];
scanf("%s",a);
for(i=1;i<2*n-1;i++){
scanf("%s",b);
for(j=0;j<strlen(b);j++)
a[j]=a[j]^b[j];
}
printf("Scenario #%d\n",++k);
printf("%s\n\n",a);
}
return 0;
}
林大OJ 1172 Find different
两个相同数字的异或值为0
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,ans,i;
cin>>n;
ans=0;
for(int j=1;j<=n;j++){
cin>>i;
ans=ans^i;
}
cout<<ans<<endl;
return 0;
}
林大OJ 1205 和为K–二进制枚举
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,i,f=1;
long long k;
while(cin>>n>>k)
{
getchar();
int a[n+1];
for(i=0; i<n; i++)
cin>>a[i];
for(i=0; i<(1<<n); i++)
{
int sum=0;
for(int j=0; j<n; j++)
{
if(i&(1<<j))
{
sum+=a[j];
}
}
if(sum==k)
{
cout<<"Yes"<<endl;
f=0;
break;
}
}
if(f==1)
cout<<"No"<<endl;
}
return 0;
}
林大OJ 1285 趣味解题
重点在于概率的运算以及利用二进制枚举将其表示的过程
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t,n,i,j,x;
double a[15],b[15],c[15],ans,ac[15],wc[15];//ac[i]表示做对第i题的概率,wc[i]表示做不出第i题的概率
cin>>t;
while(t--){
cin>>n;
for(i=0;i<n;i++)
cin>>a[i];
for(i=0;i<n;i++)
cin>>b[i];
for(i=0;i<n;i++)
cin>>c[i];
cin>>x;
ans=0;
for(i=0;i<(1<<n);i++){
int num=0;
double p=1;
for(j=0;j<n;j++){
wc[j]=(1-a[j])*(1-b[j])*(1-c[j]);//3个人都不会做该题的概率,是团队做不出该题的概率
ac[j]=(1-wc[j]);
if(i&(1<<j)){
p=p*ac[j];
num++;//记录团队的ac题数
}
else{
p=p*wc[j];
}
}
if(num==x)
ans=ans+p;
}
printf("%.4lf\n",ans);
}
return 0;
}
林大OJ 1505 陈老师加油
陈老师的初始油量必须存到一个新的变量里,每次循环可能会有不符合条件的油量剩余,对下次循环带来影响。
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t,ans=0,k1,k2,tmp;
cin>>t;
for(int i=0;i<(1<<15);i++){
k1=k2=0;
tmp=t;//初始油量存入临时变量t里
for(int j=0;j<15;j++){
if(i&(1<<j)){
k2++;
tmp*=2;
}
else{
k1++;
tmp-=1;
if(tmp<=0)
break;
}
}
if(k1==10 && k2==5 && tmp==0)
ans++;
}
cout<<ans<<endl;
return 0;
}
林大OJ 1518 纸牌游戏
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,p,i,j,ans,a[21];
ans=0;
cin>>n>>p;
for(i=0;i<n;i++)
cin>>a[i];
for(i=0;i<(1<<n);i++){
int sum=0;
for(j=0;j<n;j++){
if(i&(1<<j))
sum+=a[j];
}
if(sum==p)
ans++;
}
cout<<ans<<endl;
return 0;
}
林大OJ 1641 权利指数
先选出任意个小团体,选出来后做好标记(flag=1),并保证他们的票数之和小于等于总票数的一半,之后在没被选出来的小团体(flag=0)中再选出任意一个小团体,设他的票数为a[j],若加上a[j]后票数之和大于总票数的一半,那么这个a[j]就是“关键加入者”,则他的权利指数+1。
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t,n,a[21],b[21],flag[21],k,i,j;
cin>>t;
for(k=1;k<=t;k++){
memset(b,0,sizeof(b));
cin>>n;
int sum=0;
for(i=0;i<n;i++){
cin>>a[i];
sum+=a[i];
}
for(i=0;i<(1<<n);i++){
int x1=0;
memset(flag,0,sizeof(flag));
for(j=0;j<n;j++){
if(i&(1<<j)){
x1+=a[j];
flag[j]=1;
}
}
if(x1<=(sum/2)){
for(j=0;j<n;j++){
if(x1+a[j]>(sum/2) && flag[j]==0)
b[j]++;
}
}
}
for(i=0;i<n-1;i++)
cout<<b[i]<<" ";
cout<<b[n-1]<<endl;
}
return 0;
}
林大OJ 1665 四糸乃买花–二进制枚举
只要你写着四糸乃,我就必须得做出来!!
本题就是裸的二进制枚举,有两个需要注意的地方:一是花钱数小于等于现有钱数才能去买,二是因为题目要求不能一朵花不买,所以从1开始枚举,因为不能全部买走,所以枚举到2的n次幂-2(2的n次幂-1为全选)。然后就枚举情况,对所有满足条件的情况答案数++,最后输出答案数即可。
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,a[23],ans=0,i,j;
long long w;
cin>>n;
getchar();
for(i=0;i<n;i++)
cin>>a[i];
getchar();
cin>>w;
for(i=1;i<(1<<n)-1;i++){//因为题目要求不能一朵花不买,所以从1开始枚举,因为不能全部买走,所以枚举到2的n次幂-2(2的n次幂-1为全选)
int num=0;//记录买花数
int sum=0;//记录买花花的总钱数
for(j=0;j<n;j++){
if(i&(1<<j)){
sum+=a[j];
num++;
if(w==0) break;
}
}
if(num%4==0 && (w-sum)%4==0&&(w-sum)>=0)//剩下的钱必须为正数
ans++;
}
cout<<ans<<endl;
return 0;
}