题解

哈哈,很久不没写博客了,这次经过大家的努力,学校首次举办程序设计大赛,出了几个水题坑大家,在这也写一篇题解,供感兴趣的童鞋学习,本人是学弱,如有不清楚的地方,可以百度自行解决,本文只是起参考作用,如有错误欢迎指正。

一:过桥,这题数据出了很久了,数据上传oj时没有修改,导致大家在做题时出了点小状况,表示sorry,本题很简单,就只是对字符串的处理,假设用 一个整形变量ans记录结果,读入一个字符串然后扫描该字符串遇到‘w’ ans+=2,遇到‘m’ans+=1,遇到‘m’继续往后扫描就好了,要注意的是,答案是 ans<=30 的,所以如果当前 ans==29 然后下一字符为‘w’便直接结算算法就好了,应为ans+2=31>30。下面是我的代码:
  1. #include<iostream>
  2. #include<string>

  3. using namespace std;

  4. int main(){
  5.     int T,ans;
  6.     cin>>T;
  7.     string str;
  8.     while(T--){
  9.         cin>>str;
  10.         ans=0;
  11.         for(int i=0;i<str.length() &&ans<=30 ;i++ ){

  12.             if(str[i]=='w' )
  13.                 ans+=2;
  14.             if(str[i]=='m' )
  15.                 ans+=1;
  16.         }
  17.         if(ans>30)
  18.             cout<<30<<endl;
  19.         else
  20.             cout<<ans<<endl;
  21.     }
  22.     return 0;
  23. }
二:排序,原本是出的10w个数据,只有用scanf()和printf()输入输出,并且用快排或者堆排序方可通过,但后来考虑坑题已经过多了,这个就不坑大家了就把数据改小了,排序算法我就不多说了,下面是代码,我用了stl里的sort()函数,该函数的具体使用大家可以百度,
#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
const int maxn=10005;
int a[maxn];
int main(){
    int T,n;
    scanf("%d",&T);
    while(T--){
       scanf("%d",&n);
       for(int i=0;i<n;i++)
         scanf("%d",&a[i]);
       sort(a,a+n);
       printf("%d",a[0]);
       for(int i=1;i<n;i++)
          printf(" %d",a[i]);
       printf("\n");

    }
    return 0;
}

三:poor dog,这个题是一个经典的深搜问,深搜广搜都能过,网上也有详细的解答




深搜的做法是搜出所有的路径,然后取最短的路径作为衡量标准,
广搜是直接一次广度优先收索找到的路径便是最短路径。
该题输入的是一个邻接矩阵,然后在输入4个整数,这里给出深搜代码:
  1. #include<iostream>
  2. #include<stack>
  3. #define min(a,b) a<=b?a:b
  4. using namespace std;
  5. const int maxn=15;
  6. int n,m;
  7. int a[maxn][maxn];
  8. int ans,x2,y2;
  9. void dfs(int X, int Y, int step) {
  10.      if (X == x2 && Y == y2) {
  11.         ans = min(ans, step);
  12.         return;
  13.      }

  14.     if (a[X][Y]==1 || X < 0 || X == n+1 || Y < 0 || Y == m+1 ) {
  15.         return;
  16.     }

  17.     a[X][Y] = 1;
  18.     step++;
  19.     dfs(X - 1, Y, step);
  20.     dfs(X + 1, Y, step);
  21.     dfs(X,Y + 1, step);
  22.     dfs(X,Y - 1, step);
  23.     a[X][Y] = 0;
  24. }

  25. int main(){
  26.     int T;
  27.     cin>>T;
  28.     while(T--){
  29.         ans=999;
  30.         int x1,y1;
  31.         cin>>n>>m;
  32.         for(int i=1;i<=n;i++){
  33.             for(int j=1;j<=m;j++){
  34.                 cin>>a[i][j];
  35.             }
  36.         }
  37.         for(int i=0;i<=n+1;i++){
  38.             a[i][0]=1;a[i][m +1]=1;
  39.         }
  40.         for(int i=0;i<=m+1;i++){
  41.             a[0][i]=1;a[n+1][i]=1;
  42.         }
  43.         cin>>x1>>y1>>x2>>y2;
  44.         dfs(x1, y1, 0);
  45.         if(ans>=20){
  46.             cout<<"poor dog"<<endl;
  47.         }
  48.         else{
  49.             cout<<"luck dog"<<endl;
  50.         }


  51.     }

  52.     return 0;
  53. }
四:单词统计,这个题我觉得是很简单的一个题了,以为很多人回过,数据量不大,即使暴力一个一个统计也能统计出来,当然我的初衷是考考大家map映射容器


定义一个map 就只需要包所有单词扔map容器里,然后在输出就好,代码也很简短:
#include<iostream>
#include<map>
#include<string>
 
using namespace std;
int main(){
    map Mymap;
    string str;
    while(cin>>str){
        Mymap[str]++;
    }
    map::iterator it;
    it=Mymap.begin();
    for(;it!=Mymap.end();it++)
            cout<< it->first<<":"<< it->second<<endl;
    return 0;
}
五:积分,这个题我想直接贴代码算了,就是输入一个函数的系数和指数,如f(x) = 1 + 3x^2 + 2x^4求∫f(x)dx = x + x^3 + (2/5)x^5,估计大家觉得麻烦的就只有化简,求积分就是指数加1,系数除以新指数,这里化简有一个函数 叫 gcd(int a,int b)返回值是a,b的最大公约数,所以 a/gcd(a,b)/ b/gcd(a,b) 及为最简分数了,这里给出代码,代码中有gcd函数的实现,想了解gcd的原理可以百度“辗转相除”


  1. #include<iostream>
  2. #include<fstream>
  3. #include<ctime>
  4. #include<cstdlib>
  5. #include<algorithm>
  1. using namespace std;
  2. const int maxn=2010;

  3. int gcd(int a,int b){
  4.     return b==0?a:gcd(b,a%b);
  5. }

  6. int main(){
  7.     int a[maxn];
  8.     int T;
  9.     cin>>T;
  10.     while(T--){
  11.          int n;
  12.          cin>>n;
  13.         n*=2;
  14.         for(int i=1;i<=n;i++){
  15.             cin>>a[i];
  16.         }

  17.         for(int i=2;i<=n;i=i+2){
  18.            if(a[i-1]%(a[i]+1) == 0){
  19.                 cout<<a[i-1]/(a[i]+1)<<" "<<a[i]+1;
  20.                 if(i!=n)
  21.                     cout<<" ";
  22.            }
  23.            else{
  24.                 if(a[i-1]<0){
  25.                   a[i-1]*=-1;
  26.                   int tmp=gcd(a[i-1],a[i]+1);
  27.                   cout<<"-"<<a[i-1]/tmp<<"/"<<(a[i]+1)/tmp<<" "<<a[i]+1;
  28.                   if(i!=n)
  29.                       cout<<" ";
  30.                 }
  31.                 else{
  32.                     int tmp=gcd(a[i-1],a[i]+1);
  33.                     cout<<a[i-1]/tmp<<"/"<<(a[i]+1)/tmp<<" "<<a[i]+1;
  34.                     if(i!=n)
  35.                        cout<<" ";
  36.                 }
  37.            }

  38.         }
  39.         cout<<endl;

  40.     }
  41.     return 0;
  42. }
六:tdap的数学,这是一个经典的题目



这两个博客已经讲得非常的清楚了,而且都给出了证明过程,我就不写了,因为数据不一样,下面是我的代码大家可以参考:
  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdio>
  4. #include<cstdlib>


  5. using namespace std;


  6. typedef long long LL;
  7. const LL mod=1000000007;
  8. LL ans;
  9. struct matrix{
  10.      LL a[3][3];
  11. }A,B;


  12. matrix mult2(matrix A,matrix B){  
  13.     matrix C;
  14.     for(int i=1;i<=2;i++){  
  15.         for(int j=1;j<=2;j++){    
  16.             C.a[i][j]=0;
  17.             for(int k=1;k<=2;k++){  
  18.                 C.a[i][j] = (C.a[i][j] + A.a[i][k]*B.a[k][j])%mod;
  19.             }        }
  20.     }
  21.     return C;
  22. }


  23. matrix mult(matrix A,LL n){  
  24.     if(n==1) return A;
  25.     A = mult(A,n/2);
  26.     if(n%2==0)  return  A = mult2(A,A);
  27.     return  A = mult2(mult2(A,A),B);
  28. }


  29. int main(){
  30.     int T;
  31.     int n,a,b,x0,x1;
  32.     LL ans;
  33.     scanf("%d",&T);
  34.     while(T--){
  35.        scanf("%d%d%d%d%d",&n,&a,&b,&x0,&x1);
  36.        if(n==1){
  37.           printf("%d\n",x1);
  38.           continue;
  39.        }
  40.        A.a[1][1]=a;
  41.        A.a[1][2]=b;
  42.        A.a[2][1]=1;
  43.        A.a[2][2]=0;
  44.        B=A;
  45.        A = mult(A,n-1);


  46.        ans = ((A.a[1][1]*x1)%mod + (A.a[1][2]*x0)%mod)%mod;
  47.        printf("%lld\n",ans);
  48.     }


  49.     return 0;
  50. }
七:魔法,这是线段树,用主席树也可以,这里不详说,有兴趣可以去学习线段树,树状数组,主席树等高级数据结构,这都是很有用的数据结构,这题就直接贴线段树写法的代码吧:




  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <algorithm>
  5. #include <cmath>
  6. #include <vector>
  7. using namespace std;
  8. #define lson 2*u
  9. #define rson 2*u+1
  10. const int maxn=100010;
  11. int n,m;
  12. struct tnode{
  13.     int l,r,cnt;
  14.     int a[10];
  15.     int getmid(){
  16.         return (l+r)/2;
  17.     }
  18. }tree[4*maxn];
  19. void build(int l,int r,int u){
  20.     tree[u].l=l,tree[u].r=r,tree[u].cnt=0;
  21.     memset(tree[u].a,0,sizeof(tree[u].a));
  22.     if (l==r){
  23.         return ;
  24.     }
  25.     int mid=tree[u].getmid();
  26.     build(l,mid,lson);
  27.     build(mid+1,r,rson);
  28. }
  29. void update(int l,int r,int u,int c){
  30.     if (tree[u].l==l&&tree[u].r==r){
  31.         tree[u].cnt+=c;
  32.         int Max=min(10,r-l+1);
  33.         for (int i=0;i<Max;i++) tree[u].a[i]+=c;
  34.         return ;
  35.     }
  36.     int mid=tree[u].getmid();
  37.     if (r<=mid) update(l,r,lson,c);
  38.     else if (l>mid) update(l,r,rson,c);
  39.     else{
  40.         update(l,mid,lson,c);
  41.         update(mid+1,r,rson,c);
  42.     }
  43.     int Max=min(tree[u].r-tree[u].l+1,10);
  44.     for (int i=0,j=0,k=0;k<Max;){
  45.         if (tree[lson].a[i]>tree[rson].a[j]) tree[u].a[k++]=tree[lson].a[i++]+tree[u].cnt;
  46.         else tree[u].a[k++]=tree[rson].a[j++]+tree[u].cnt;
  47.     }
  48. }
  49. int ans[10];
  50. void query(int l,int r,int u,int K){
  51.     if (tree[u].l==l&&tree[u].r==r){
  52.         int Max=min(r-l+1,10);
  53.         vector<int> v;
  54.         for (int i=0;i<Max;i++) v.push_back(tree[u].a[i]+K);
  55.         for (int i=0;i<10;i++) v.push_back(ans[i]);
  56.         sort(v.begin(),v.end(),greater<int>());
  57.         for (int i=0;i<10;i++) ans[i]=v[i];
  58.         return ;
  59.     }
  60.     int mid=tree[u].getmid();
  61.     if (r<=mid) query(l,r,lson,K+tree[u].cnt);
  62.     else if (l>mid) query(l,r,rson,K+tree[u].cnt);
  63.     else{
  64.         query(l,mid,lson,K+tree[u].cnt);
  65.         query(mid+1,r,rson,K+tree[u].cnt);
  66.     }
  67. }
  68. int main()
  69. {
  70.     char cmd[10];
  71.     int l,r,K;
  72.     while(~scanf("%d%d",&n,&m)){
  73.         build(1,n,1);
  74.         while(m--){
  75.             scanf("%s%d%d%d",cmd,&l,&r,&K);
  76.             if (cmd[0]=='A') update(l,r,1,K);
  77.             else{
  78.                 memset(ans,0,sizeof(ans));
  79.                 query(l,r,1,0);
  80.                 int tt=0;
  81.                 for (int i=0;i<K;i++) tt+=ans[i];
  82.                 printf("%d\n",tt);
  83.             }
  84.         }
  85.     }
  86.    
  87.     return 0;
  88. }

八:谁是赢家,关大神已经证明过了,这直接贴博文链接


  1. #include<iostream>
  2. using namespace std;
  3.   
  4. int main(){
  5.     int T;
  6.     cin>>T;
  7.     while(T--){
  8.         int m,n;
  9.         cin>>n>>m;
  10.         if(n%(m+1)==0)
  11.             cout<<"tdap"<<endl;
  12.         else
  13.             cout<<"xsong"<<endl;
  14.     }
  15.     return 0;
  16. }
九:max sum,这是一道很简单的动态规划,看了代码你一定会的,代码如下:
  1. #include<iostream>
  2. using namespace std;


  3. int main(){
  4.     int n;
  5.     cin>>n;
  6.     while(n--){
  7.         int sum=0;
  8.         int f,k=0,tmp;
  9.         cin>>tmp;
  10.         for(int i=0;i<tmp;i++){
  11.             cin>>f;
  12.             k+=f;
  13.             if(k>sum)
  14.                 sum=k;
  15.             if(k<=0)
  16.                k=0;
  17.         }
  18.         cout<<sum<<endl;
  19.     }
  20.     return 0;
  21. }
其他的题感觉没什么好说的了,有问题可以QQ小刀关大神,或者找本学弱给你粗略讲解
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值