NENU ACM 14级训练赛 2014-12-21(年度收官战)

来源:互联网 发布:单词记忆方法知乎 编辑:程序博客网 时间:2024/05/24 01:27

啥也不说了,直接看........题解。


A题:a+b

是个人就能过~


B题:排序

N就1000,你想咋排就咋排

#include<cstdio>#include<algorithm>using namespace std;const int M=1024;int a[M];int main(){    int t,n;    while(~scanf("%d",&t)){        while(t--){            scanf("%d",&n);            for(int i=0;i<n;i++){                scanf("%d",&a[i]);            }            sort(a,a+n);            for(int i=0;i<n;i++){                printf("%d%c",a[i],i==n-1?'\n':' ');            }        }    }    return 0;}


C题:二进制枚举

题目看着好像很厉害的样子,其实一看数据量,披萨上能放的东西的种类是16种。

对于披萨,这些东西就放或不放两种状态,总状态共2^16种,枚举这些状态,然后验证状态是否满足所有人的要求就可以了。

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>using namespace std;#define M 10000struct request {    int want;    int dont;} req[M];int len=0;char result[M][100];int cnt=0;int input() {    int j,want,dont;    char str[100]= {0};    len=0;    while(gets(str)) {        want=0;        dont=0;        if(str[0]=='.') return 1;        for(j=0; str[j]!= ';' ; j+=2)            if(str[j]=='+')                want|= (1<<(str[j+1]-'A'));            else                dont|= (1<<(str[j+1]-'A'));        req[len].want   = want;        req[len].dont   = dont;        len++;    }    return 0;}int solve() {    int state,j,i,x=0;    char str[100]= {0};    for(state=0; state<(1<<16); state++) {        for(j=0; j<len; j++)            if( (state&req[j].want) || ( (~state)&req[j].dont) )                continue;            else                break;        if(j==len) {            strcpy(result[cnt], "Toppings: ");            for(i=0; i<16; i++)                if( state& (1<<i) )                    str[x++]    = 'A'+i;            str[x]=0;            strcat(result[cnt], str);            cnt++;            return 1;        }    }    strcpy(result[cnt],"No pizza can satisfy these requests.");    cnt++;    return 0;}void output() {    int i;    for(i=0; i<cnt; i++)        printf("%s\n",result[i]);}int main() {    int res=0;    while(1) {        res = input();        if(!res)    break;        solve();    }    output();    return 0;}



D题:BFS

vincent找的宽搜入门题,还是不错滴

#include<cstdio>#include<cstring>#include<queue>#define mt(a,b) memset(a,b,sizeof(a))using namespace std;const int M=1e5+10;bool vis[M];int n,k;struct Q{    int id,step;}now,pre;queue<Q> q;void solve(int x){    if(x<0||x>1e5||vis[x]) return ;    vis[x]=true;    now.id=x;    now.step=pre.step+1;    q.push(now);}int bfs(){    vis[n]=true;    now.id=n;    now.step=0;    while(!q.empty()) q.pop();    q.push(now);    while(!q.empty()){        pre=q.front();        q.pop();        if(pre.id==k) return pre.step;        solve(pre.id+1);        solve(pre.id-1);        solve(pre.id*2);    }}int main(){    while(~scanf("%d%d",&n,&k)){        mt(vis,0);        printf("%d\n",bfs());    }    return 0;}

E题:模拟

求给出的日期范围内素数月素数日的个数。

对于一般的日期模拟的题目,给一个笨笨的好方法,那就是一天一天的去模拟、去判断,因为一般日期范围都不会太大,写出的代码虽然丑,但是有保障,好调试。

本题就是这样,判断区间内每一天是否为素数月素数日。

注意闰年的影响。

#include<iostream>  #include<cstdio>  #include<cstring>  #include<cmath>  using namespace std;  int x[110];  int noleap[]= {0,0,9,11,0,11,0,11,0,0,0,10,0};//noLeap  int leap[]= {0,0,10,11,0,11,0,11,0,0,0,10,0};//Leap  int a1[]={0,31,29,31,30,31,30,31,31,30,31,30,31};//Leap  int a2[]={0,31,28,31,30,31,30,31,31,30,31,30,31};//noLeap  bool isleap(int y){//判断是否为闰年      if((y%4==0&&y%100!=0)||y%400==0){          return true;      }      else return false;  }    void isprime(){//筛素数      memset(x,1,sizeof(x));      x[0]=0;      x[1]=0;      for(int i=2;i<=sqrt(100)+1;i++){          if(!x[i]) continue;          for(int j=(i<<1);j<=100;j+=i){              x[j]=0;          }      }  }    int main(){      isprime();      int n,y1,m1,d1,y2,m2,d2;      int ans;      int i,j,k;      while(~scanf("%d",&n)){          while(n--){              ans=0;              scanf("%d%d%d%d%d%d",&y1,&m1,&d1,&y2,&m2,&d2);              i=y1;//年              j=m1;//月              k=d1;//日              while(1){                  if(i==y2&&j==m2&&k==d2) break;                  if(isleap(i)){                      if(x[j]){                          if(x[k]){                              ans++;                          }                      }                      if(k==a1[j]){                          j++;                          k=1;                      }                      else{                          k++;                      }                  }                  else{                      if(x[j]){                          if(x[k]){                              ans++;                          }                      }                      if(k==a2[j]){                          j++;                          k=1;                      }                      else{                          k++;                      }                  }                  if(j>12){                      i++;                      j=1;                      k=1;                  }              }              if(x[m2]&&x[d2]) ans++;//判断最后一天              printf("%d\n",ans);          }      }      return 0;  }  


F题:进制转换

求出a*b=c是哪个进制下的转换

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>using namespace std;int trans(int t,int b) {    int k = 1;    int ret = 0;    while (t>0) {        ret += (t%10)*k;        t /= 10;        k *= b;    }    return ret;}int main() {    int Cas,minn,k,p,q,r;    int a,b,c;    scanf("%d",&Cas);    while (Cas--) {        scanf("%d%d%d",&p,&q,&r);        a = p;        b = q;        c = r;        minn = 0;        while (a>0) {            if (minn<a%10) minn = a%10;            a /= 10;        }        while (b>0) {            if (minn<b%10) minn = b%10;            b /= 10;        }        while (c>0) {            if (minn<c%10) minn = c%10;            c /= 10;        }        int i;        for (i=minn+1; i<=16; i++) {            a = trans(p,i);            b = trans(q,i);            c = trans(r,i);            if (a*b == c) break;        }        if (i == 17) i = 0;        printf("%d\n",i);    }    return 0;}


G题:由于此题需要另一题的背景,不做,略过。


H题:高精度

#include<iostream>#include<string>#include<cmath>#include<cstring>#include<cstdio>using namespace std;const int M = 500;int a[M];int b[M];char s1[M],s2[M];int main() {    int Cas,i,time=1;    scanf("%d",&Cas);    while(Cas--) {        memset(a,0,sizeof(a));        memset(b,0,sizeof(b));        scanf("%s%s",s1,s2);        int len1=strlen(s1);        int len2=strlen(s2);        for(i=len1-1; i>=0; i--) {            a[len1-1-i]=(int)(s1[i]-'0');        }        for(i=len2-1; i>=0; i--) {            b[len2-1-i]=(int)(s2[i]-'0');        }        int maxlen;        if(len1>len2) maxlen = len1;        else          maxlen = len2;        for(i=0; i<=maxlen+100; i++) {            a[i]=a[i]+b[i];            while(a[i]>1) {                a[i+1]++;                a[i]-=2;            }        }        for(i=maxlen+100; i>=0; i--) {            if(a[i]) break;        }        printf("%d ",time);        if(i==-1&&a[0]==0){            printf("0");        }        else {            for(; i>=0; i--) {                printf("%d",a[i]);            }        }        puts("");        time++;    }    return 0;}


I题:栈贪心模拟

给出城市的正视图,所有的大楼都是矩形,给出每个高度改变时的坐标,问最少可以看出有几个大楼。
可以看出,w和横坐标是没有用的。。。

用栈模拟,先将0压栈,然后遍历n个数,设当前高度为y,如果栈顶元素大于y的话,说明栈顶元素所代表的高度的楼找到了,就不断弹出栈顶元素并ans+1直到栈顶元素小于等于y,如果此时栈顶元素小于y的话,就将y压栈,否则continue。

#include<iostream>  #include<cmath>  #include<cstring>  #include<stack>  #include<cstdio>  #define PI acos(-1.0)  #define inf 0x3f3f3f3f  #define E exp(double(1))  #define eps 1e-7  using namespace std;    #ifdef __LL64  typedef __LL64 LL;  #else  typedef long long LL;  #endif    const int MAXN = 60000;  int x,y[MAXN];    int main() {      int n,w;      while(~scanf("%d%d",&n,&w)) {          for(int i=0; i<n; i++) {              scanf("%d%d",&x,&y[i]);          }          y[n]=0;            stack<int> st;          int ans = 0;          st.push(0);          for(int i=0; i<=n; i++) {              while(st.top()>y[i] && !st.empty()) {                  st.pop();                  ans++;              }              if(y[i]!=st.top()) {                  st.push(y[i]);              }          }          printf("%d\n",ans);      }      return 0;  }  


J题:二分

这是道被各种数据结构和算法碾压过的题,可以用二分、哈希、map、字典树这些玩意儿一一碾压过去。

这里讨论二分的做法,首先给字符串排个序,然后输入一个,就进行二分查找。

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>using namespace std;int k;struct Dictionary{    char s1[12];    char s2[12];}d[100100];bool cmp(Dictionary A,Dictionary B){    if(strcmp(A.s2,B.s2) == 1) return false;    return true;}void binarySearch(char str[]){    int L = 0;    int R = k-1;    while(L<=R){        int mid = (L+R)>>1;        if(!strcmp(d[mid].s2,str)){            puts(d[mid].s1);            return;        }        if(~strcmp(d[mid].s2,str)) R = mid - 1;        else                       L = mid + 1;    }    puts("eh");    return;}int main(){    k = 0;    char tmp;    while(1){        tmp = getchar();        if(tmp == '\n') break;        d[k].s1[0] = tmp;        scanf("%s%s",d[k].s1+1,d[k].s2);        k++;        tmp = getchar();    }    sort(d,d+k,cmp);//    for(int i=0;i<k;i++){//        printf("%s---%s\n",d[i].s1,d[i].s2);//    }    char str[12];    while(~scanf("%s",str)){        binarySearch(str);    }    return 0;}


0 0