这题迷之错误,我给大家写题解,大家要是过了这题可以给我题解不...
题意:给出一个n,一个x,接下来有n个数,我可以从中选择若干个数进行或运算,如果等于x,我就寻到宝藏,但是老板很坏,他不想让我寻到宝藏,他就把n个数中的某些数改掉,不让我得到x,求老板修改数字个数的最小值。
思路:举个例子:有4个数:15,3,2,5,x=7(就是二进制的111),把所有数换成二进制,15=1111,因为有了一个111没有的1,所有这个数对答案无影响,排除,3=11,2=10,5=101,统计每位1的个数,从右边开始第一个1有两个,第二个1有两个,第三个1有一个,那么答案就是这些数的最小值,就是1。
#include<cstdio>
#include<algorithm>
using namespace std;
int main()
{
int n;
int k,t;
while(~scanf("%d%d",&n,&k))
{
int vis[50]={0};
for(int i=0;i<n;i++)
{
scanf("%d",&t);
if(((t|k)^k)!=0) //如果这个数某一位是1而k的这位是0,排除
continue;
for(int j=0;j<32;j++)
if((t&(1<<j))!=0) //位运算优先级低,千万记得加括号
vis[j]++;
}
int ans=999999;
for(int i=0;i<32;i++)
if((k&(1<<i))!=0)
ans=min(ans,vis[i]);
if(ans==999999)
ans=0;
printf("%d\n",ans);
}
}
C CSU 2056 a simple game
这题其实很简单,如果第二个字符串是第一个字符串的子串,那么肯定输出Yes,当然第二个字符串要记得把所有多余的0排除掉,前缀0后缀0都要排除,接下来就是KMP算法字符串匹配了
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<vector>
using namespace std;
char s1[1000005],s2[1000005],temp[1000005];
int next1[1000005];
void get()
{
int i,j,len=strlen(s2);
next1[0]=-1;
for(i=0,j=-1;i<len;)
if(j==-1||s2[i]==s2[j])
next1[++i]=++j;
else
j=next1[j];
}
int kmp()
{
int i,j,n,len;
get();
n=strlen(s1);
len=strlen(s2);
for(i=j=0;i<n;)
{
if(j==-1||s1[i]==s2[j])
i++,j++;
else
j=next1[j];
if(j>=len)
return 1;
}
return 0;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%s%s",s1,s2);
int len1=strlen(s1);
int len2=strlen(s2);
if(len2==1&&s2[0]=='0')
{
printf("Yes\n");
continue;
}
int p=0;
while(s2[p]=='0'&&p<len2)//排0
p++;
int p1=len2-1;
while(s2[p1]=='0'&&p1>=0)
p1--;
if(p==len2||p1<0)
{
printf("Yes\n");
continue;
}
int tot=0;
for(int k=p;k<=p1;k++)
{
temp[tot++]=s2[k];
}
temp[tot]='\0';
strcpy(s2,temp);
len2=strlen(s2);
if(len1<len2) //第二个串长于第一个串,那第二个串肯定不是第一个串的子串
{
printf("No\n");
continue;
}
int flag=kmp();
if(!flag)//没匹配到,翻转第二个串继续匹配
{
for(int i=0;i<len2;i++)
{
temp[len2-i-1]=s2[i];
}
temp[len2]='\0';
strcpy(s2,temp);
flag=kmp();
}
if(flag)
printf("Yes\n");
else
printf("No\n");
}
}
水题直接上代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<vector>
using namespace std;
int a[1000005];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,i,k,sum=0;
scanf("%d%d",&n,&k);
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
}
for(i=2;i<n;i++)
{
if(a[i]>a[i-1]&&a[i]>a[i+1])
sum++;
}
if(sum==k)
printf("Yes\n");
else
printf("No\n");
}
}
把Z的边看成无限长,加入第N个Z时,会和前面每一个Z都有9个交点,那么一共增加9*(N-1)个交点,并且会增加9*(N-1)+1个区域,即f[ n ]=f[ n-1 ]+9*(n-1)+1,再推一下变成等差数列求和公式f[ n ]=n+1+9*n*(n-1)/2
#include<cstdio>
#include<cstring>
using namespace std;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
long long n,ans;
scanf("%lld",&n);
printf("%lld\n",n+1+n*(n-1)*9/2);
}
}
搜索题,这个题就是三个水杯的加强版,三个水杯的原型题是三个水杯(南阳oj 21),首先要会三个水杯的解法,然后这个题我加了个f 数组,用来记录这个状态的父亲,我把b水杯目前水量乘以1001+c水杯目前水量表示为 一个状态, 比如12 0 0下一次倒水可能变成7 0 5,那么父亲是 0*1001+0=0,儿子是0*1001+5=5,f[ 5 ]=0,这样就可以在找到最优解的时候顺便把他上层的所有状态表示出来
#include<cstdio>
#include<cstring>
#include<stack>
#include<algorithm>
using namespace std;
const int maxn=1000+10;
const int inf=9999999;
int vis[maxn][maxn],f[maxn*maxn];
int c1,c2,c3,d,flag,ans;
void init()
{
for(int i=0;i<maxn;i++)
memset(vis[i],0,sizeof(vis[i]));
ans=inf;
}
void dfs(int a,int b,int c,int step,int father)
{
if(vis[b][c]&&vis[b][c]<=step)
return;
vis[b][c]=step;
f[b*1001+c]=father;
if(a==d||b==d||c==d)
{
if(ans>step)
flag=b*1001+c;
ans=min(ans,step);
return;
}
int t=min(c2-b,a);
if(t)
dfs(a-t,b+t,c,step+1,b*1001+c);
t=min(c3-c,a);
if(t)
dfs(a-t,b,c+t,step+1,b*1001+c);
t=min(c1-a,b);
if(t)
dfs(a+t,b-t,c,step+1,b*1001+c);
t=min(c3-c,b);
if(t)
dfs(a,b-t,c+t,step+1,b*1001+c);
t=min(c1-a,c);
if(t)
dfs(a+t,b,c-t,step+1,b*1001+c);
t=min(c2-b,c);
if(t)
dfs(a,b+t,c-t,step+1,b*1001+c);
}
void print(int num)
{
if(num!=-1)
{
print(f[num]);
int c=num%1001;
int b=num/1001;
int a=c1-b-c;
printf("%d %d %d\n",a,b,c);
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int a,b,c;
scanf("%d%d%d%d",&c1,&c2,&c3,&d);
init();
dfs(c1,0,0,0,-1);
if(ans==inf)
printf("-1\n");
else
{
printf("%d\n",ans);
f[0]=-1;
print(flag);
}
}
}