2011湖南第七届省赛

来源:互联网 发布:java把数组变成字符串 编辑:程序博客网 时间:2024/04/26 23:02

http://vjudge.net/contest/view.action?cid=50014#problem/E

E - Box Game

思路:

这种简单的博弈,一般的思路是:有一个必输态(P),还有很多必胜态(N),一个状态要是可以达到一个必输态的话,当前的这种状态为必胜态,如果只能到达必胜态的话,当前状态必为必输状态。.本题当面对最大值为2时为必N(胜态),那么3为p(必输),4为N,5为N,6为N,7为P,8为N。。。。。。13为N,14为N,15为P。。。。。。

4一定能到3,5一定能到3,6一定能到3,7只能到4、5、6状态(全为必胜态),则7为P。这么一直推导下去会发现只要面临了2^n-1时,则必输。


#include<stdio.h>#include<stdlib.h>#include<string.h>#include<ctype.h>int main() {    int n;    while(~scanf("%d",&n),n){        int tmp=n+1;        bool flag=false;        while(tmp>=2){            if(tmp%2!=0){                flag=true;            }            tmp=tmp>>1;        }        if(flag==false) printf("Bob\n");        else printf("Alice\n");    }    return 0;}


B - Counting Game
题意:

要求第m个人,举k次手时,数报道了什么地方。(一定会有解的,因为很多以七开头的数,数大到一定的程度后每个人一定能聚到一百次手的,比如7 x x x x,那么一定能让100个人,每个人都举一百次手)

在m出可能数字满足以下规律,注意在最左边和最右边的地方要特殊处理一下。

#include<stdio.h>#define MAX 1<<30bool deal(int num) {bool flag=false;    if(num%7==0) {        flag=true;    } else {        int tmp=num;        while(tmp) {            if(tmp%10==7) {                flag=true;                break;            }            tmp=tmp/10;        }    }    if(flag==true) return true;    else return false;}int main() {    int n,m,k;    int num[50000];    while(~scanf("%d %d %d",&n,&m,&k),(n||m||k)) {        int cnt=2;        int ans=0;        num[1]=m;        if(deal(m)==true)ans++;        for(int i=2; i<MAX; i++) {            if(i%2==0) {if(n==m)continue;//如果在最右边那么要跳过,否则就会数2次(题目要求下一轮从第n-1‡人开始数)                num[cnt]=num[cnt-1]+2*(n-m);//num[cnt-1]+(n-m)+((n-1)-m+1) (n-m)向左边的要数的数,((n-1)-m+1)从最左边回到m要数的数                if(deal(num[cnt])==true) ans++;                cnt++;            } else if(i%2==1){if(m==1) continue;//如果在最左边,则在下一轮的时候,应该跳过,否则会数2次(题目要求下一轮从第2人开始数)                num[cnt]=num[cnt-1]+2*m-2;                if(deal(num[cnt])==true) ans++;                cnt++;            }            if(ans==k) {                printf("%d\n",num[cnt-1]);                break;            }        }    }    return 0;}


C - Polyomino Composer
由于本题的数据很小,一看就是暴力做就好了。

由于无论什类型的图形,一定有一个最左上方的点,又由于本题的图形,是有两小图形只能通过平移,且没有重叠的组成的。那么同时找到大图形的最左上角的点,

对应的标记。然后再从没有被标记的点钟找到最左上的点,就能进行第二个图形的处理了。

#include<stdio.h>#include<string.h>#define MAX 25char poly1[MAX][MAX];char poly2[MAX][MAX];bool mark[MAX][MAX];struct Node{    int x;    int y;}p1,p2;int main() {    int n,m;    while(~scanf("%d %d",&n,&m),(n||m)){memset(mark,false,sizeof(mark));int num1=0;int num2=0;bool flag=false;        for(int i=0;i<n;i++){            scanf("%s",poly1[i]);            for(int j=0;j<n;j++){                if(poly1[i][j]=='*') num1++;            }        }        for(int i=0;i<m;i++){            scanf("%s",poly2[i]);            for(int j=0;j<m;j++){if(poly2[i][j]=='*'){num2++;} }        }//找p1         for(int i=0;i<n;i++){            for(int j=0;j<n;j++){                if(poly1[j][i]=='*'){                    p1.x=j;                    p1.y=i;                    flag=true;                    break;                }            }            if(flag==true) break;        }//找p2         flag=false;        for(int i=0;i<m;i++){            for(int j=0;j<m;j++){                if(poly2[j][i]=='*'){                    p2.x=j;                    p2.y=i;                    flag=true;                    break;                }            }            if(flag==true) break;        }        for(int i=0;i<m;i++){            for(int j=0;j<m;j++){                if(poly2[i][j]=='*'){                    mark[p1.x+i-p2.x][p1.y+j-p2.y]=true;                }            }        }flag=false;        for(int i=0;i<n;i++){            for(int j=0;j<n;j++){                if(poly1[j][i]=='*'&&mark[j][i]==false){                    p1.x=j;                    p1.y=i;                    flag=true;                    break;                }            }            if(flag==true){break;}        }        for(int i=0;i<m;i++){            for(int j=0;j<m;j++){                if(poly2[i][j]=='*'&&mark[p1.x+i-p2.x][p1.y+j-p2.y]==false){                    mark[p1.x+i-p2.x][p1.y+j-p2.y]=true;                }            }        }                int cnt=0;        for(int i=0;i<n;i++){            for(int j=0;j<n;j++){                if(poly1[i][j]=='*'&&mark[i][j]==true){                    cnt++;                }            }        }        if(cnt==num1&&num1==2*num2){            printf("1\n");        }else{            printf("0\n");        }    }    return 0;}/**4 3**..**....**..**....**.** 4 3.*..**..***.**..*..*..**.4 3.***.***.***........**.**4 2*...*......*...**.*. 3 2...**.**.******/
K - RMQ with Shifts

这是一道线段树模板题。

处理字符串的时候要注意,我们队两个人都犯了同样的错误:

void dealstr(char tmp[]){    int len=strlen(tmp);    cnt=0;    for(int i=6;i<len-1;){        op[cnt++]=tmp[i]-'0';        i=i+2;    }}

再有就是要注意在shift以后要,要变换原来的数组。

#include<stdio.h>#include<string.h>#include<math.h>#include<algorithm>using namespace std;#define MAX 423456//4*nint num[MAX];int segTree[MAX];char a[100];int op[100];int cnt=0;int n,m;void dealstr(char tmp[]){    int len=strlen(tmp);    cnt=0;    int ans=0;    for(int i=6;i<len;i++){        if((tmp[i]-'0')>=0&&(tmp[i]-'0')<=9){            ans=ans*10+(tmp[i]-'0');        }else{            op[cnt]=ans;            ans=0;            cnt++;        }    }}void build(int l,int r,int root){    if(l==r){        segTree[root]=num[l];        return;    }else{        int mid=(l+r)/2;        build(l,mid,root*2);        build(mid+1,r,root*2+1);        if(segTree[root*2]<segTree[root*2+1]){            segTree[root]=segTree[root*2];        }else{            segTree[root]=segTree[root*2+1];        }    }}void update(int l,int r,int root,int pos,int ind){    if(l==r){        segTree[root]=num[ind];        return;    }    int mid=(l+r)/2;    if(pos<=mid) update(l,mid,root*2,pos,ind);    else update(mid+1,r,root*2+1,pos,ind);    segTree[root]=min(segTree[root*2],segTree[root*2+1]);}void shift(){    for(int i=0;i<cnt;i++){        update(1,n,1,op[i],op[(i+1)%cnt]);    }    int tmp=num[op[0]];    for(int i=1;i<cnt;i++){        num[op[i-1]]=num[op[i]];    }    num[op[cnt-1]]=tmp;}int query(int l,int r,int from,int to,int root){    int p1,p2;    if(l>to||r<from){        return -1;    }    if(l>=from&&r<=to){        return segTree[root];    }    int mid=(l+r)/2;    p1=query(l,mid,from,to,root*2);    p2=query(mid+1,r,from,to,root*2+1);    if(p1==-1) return p2;    if(p2==-1) return p1;    if(p1<=p2) return p1;    return p2;}int main() {        scanf("%d %d",&n,&m);        for(int i=1;i<=n;i++){            scanf("%d",&num[i]);        }        build(1,n,1);        while(m--){            scanf("%s",a);            cnt=0;            dealstr(a);            if(a[0]=='q'){                int ans=query(1,n,op[0],op[1],1);                printf("%d\n",ans);            }else{                shift();            }        }    return 0;}/***7 56 2 4 8 5 1 4query(3,7)shift(2,4000,5799,7)query(1,4)shift(1,2)query(2,2)****/



0 0
原创粉丝点击