题目链接:
http://codeforces.com/contest/282
A题 Bit++
题意:求出通过一系列自增自减运算最后变量的值。不用考虑前后。水题。
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<stack>
#include<queue>
#define eps 1e-6
#define INF (1<<20)
#define PI acos(-1.0)
using namespace std;
int main()
{
int n;
char save[5];
while(scanf("%d",&n)!=EOF)
{
int x=0;
while(n--)
{
scanf("%s",save);
if(save[0]=='X')
{
if(save[1]=='-')
x--;
else
x++;
}
else
{
if(save[0]=='+')
x++;
else
x--;
}
}
printf("%d\n",x);
}
return 0;
}
B题 Painting Eggs
题意:n个蛋,两个人对每一个蛋涂漆都有一个价格,要使蛋都涂完,且两个人的付费差不超过500,问怎样分配这n个蛋。
解题思路:对每一个蛋进行贪心,如果如果给第一个人使得两人的差价低于给第二个人两人的差价,则把该蛋分给第一个人。
代码:
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<stack>
#include<queue>
#define eps 1e-6
#define INF (1<<20)
#define PI acos(-1.0)
using namespace std;
char ans[1100000];
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
int a=0,b=0,num=0;
int temp1,temp2;
while(n--)
{
scanf("%d%d",&temp1,&temp2);
if(abs(a+temp1-b)<abs(b+temp2-a))
{
ans[num++]='A';
a+=temp1;
}
else
{
ans[num++]='G';
b+=temp2;
}
}
ans[num]='\0';
if(abs(a-b)<=500)
printf("%s\n",ans);
else
printf("-1\n");
}
return 0;
}
C题 XOR and OR
题意:给两个0、1组成的字符串,可以从第一个字符串任取两个相邻的字符,通过抑或和或运算得到两个数代替取出的两个字符,问经过多次这样的操作以后能否得到第二个字符。
解题思路:找规律。11<->01或10 00<->00 它们之间是等价的。所以只要两串都含1且长度相等,一定可以转换。
代码:
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<stack>
#include<queue>
#define eps 1e-6
#define INF (1<<20)
#define PI acos(-1.0)
using namespace std;
char save1[1100000],save2[1100000];
int main()
{
while(scanf("%s%s",save1,save2)!=EOF)
{
bool flag1=false,flag2=false;
int len1=strlen(save1),len2=strlen(save2);
if(len1!=len2||(len1==1&&strcmp(save1,save2)))
{
printf("NO\n");
continue;
}
for(int i=0;i<len1;i++)
if(save1[i]=='1')
{
flag1=true;
break;
}
for(int i=0;i<len2;i++)
if(save2[i]=='1')
{
flag2=true;
break;
}
if((flag1==false&&flag2==true)||(flag1==true&&flag2==false))
printf("NO\n");
else
printf("YES\n");
}
return 0;
}
D题: Yet Another Number Game
题意:有n堆数(n<=3),有两种操作,操作一:把某一堆数减一个不大于它的数。操作二:把每一堆都减一个数m(1<=m<=min(所有数))。两人依次操作,每人都完美表现,最后不能做操作的输,问谁赢。
解题思路:当n=1时,如果数量大于0则先胜,否则先负。
当n=2时,Wythoff game.可以直接用公式,也可以用动归把所有的情况都列出来。
当n=3时,Nim game. 如果三个数的抑或为0(奇异点),则必输,否则为赢。
代码:
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<stack>
#include<queue>
#define eps 1e-6
#define INF (1<<20)
#define PI acos(-1.0)
using namespace std;
int main()
{
int n,a,b,c;
while(scanf("%d",&n)!=EOF)
{
if(n==1)
{
scanf("%d",&a);
if(a)
printf("BitLGM\n");
else
printf("BitAryo\n");
}
if(n==2)
{
scanf("%d%d",&a,&b);
bool dp[350][350];
memset(dp,false,sizeof(dp));
for(int i=1;i<=a;i++)
dp[i][0]=true;
for(int j=1;j<=b;j++)
dp[0][j]=true;
for(int i=1;i<=a;i++)
for(int j=1;j<=b;j++)
{
int flag=0;
if(i==j) //采用第二种方法
{
dp[i][j]=true;
continue;
}
else
{
int Min=min(i,j);
for(int k=1;k<=Min;k++)
if(dp[i-k][j-k]==false)
{
dp[i][j]=true;
flag=1;
break;
}
}
if(flag==1)
continue;
for(int k=1;k<=i;k++) //采用第一种方法
if(dp[i-k][j]==false)
{
flag=1;
dp[i][j]=true;
break;
}
if(flag==0)
{
for(int k=1;k<=j;k++)
if(dp[i][j-k]==false)
{
dp[i][j]=true;
flag=1;
break;
}
}
}
if(dp[a][b]==true)
printf("BitLGM\n");
else
printf("BitAryo\n");
}
if(n==3)
{
scanf("%d%d%d",&a,&b,&c);
if(a^b^c)
printf("BitLGM\n");
else
printf("BitAryo\n");
}
}
return 0;
}
E题 Sausage Maximization
题意:给n(n<=10^5)个数,然后让你求出最大的前p个数和后q个数的抑或和。
解题思路:用Trie树。贪心选择最大值。
//trie树与贪心
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<stack>
#include<queue>
#define eps 1e-6
#define INF (1<<20)
#define PI acos(-1.0)
using namespace std;
struct Node
{
struct Node * son[2];
long long data;
}*root;
long long save[110000];
struct Node * create()
{
struct Node *p=(struct Node *)malloc(sizeof(struct Node));
p->data=0;
p->son[0]=p->son[1]=NULL;
return p;
}
void insert(struct Node *cur,long long num)
{
int bit[50];
struct Node *temp=cur;
for(int i=0;i<=40;i++)
bit[i]=1&(num>>i);
for(int i=40;i>=0;i--) //都保存为50位,无所谓是从低位还是从高位
{
if(temp->son[bit[i]]==NULL)
temp->son[bit[i]]=create();
temp=temp->son[bit[i]];
}
temp->data=num;
}
long long query(struct Node *cur ,long long num)
{
int bit[50];
struct Node *temp=cur;
for(int i=0;i<=40;i++)
bit[i]=1&(num>>i);
for(int i=40;i>=0;i--) //从高位开始,贪心算法
{
if(temp->son[bit[i]^1]) //如果bit[i]=0 则应该选择son[1];如果bit[i]=1,则应该选择son[0]
temp=temp->son[bit[i]^1]; //1与其他抑或得到它的反数
else
temp=temp->son[bit[i]];
}
return num^(temp->data);
}
int main()
{
int n;
while(cin>>n)
{
root=create();
long long sum=0,ans=0;
for(int i=1;i<=n;i++)
{
cin>>save[i];
sum^=save[i];
insert(root,sum);
ans=max(ans,sum); //此时后缀为空
}
sum=0;
for(int i=n;i>=1;i--)
{
sum^=save[i];
ans=max(ans,query(root,sum));
}
cout<<ans<<endl;
}
return 0;
}