(补题心路)——“盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛

不知道该摆出什么表情
别的比赛要脑细胞,这比赛要命
水题真的是送分送到家门口但是没有这个命去交。。
热身赛的时候只有最后十分钟左右可以挣扎着交题
正式比赛的话就是,比赛5小时,挂机4小时,延时1小时……(延时的时候我实在是饿死了就去吃饭了,向仍然坚持做题的大佬低头)


!!!!下面是自己的一点学习过程!所以不会做的题目就只能空白了。。。


黑白图像直方图

描述
在一个矩形的灰度图像上,每个像素点或者是黑色的或者是白色的。黑色像素点用1表示,白色像素点用0表示。现在要求你编写一个程序,计算每列上黑色像素点的个数并输出。如下图所示是一个6∗8的黑板图像。

1 1 0 0 1 1 1 1
0 1 1 0 1 0 1 0
1 1 1 1 0 1 1 0
0 1 1 0 0 1 0 0
1 0 1 0 0 1 0 0
0 1 0 1 0 1 1 0

输入
输入有多组组。
每组的第一行有2个整数m、n,(1<=m,n<=100)。
接着有m行,每行有n个数字,每个数字是0或1,之间用一个空格分开。

输出
对图像数据,依次一行输出图像中每列黑色像素点的总数。

样例输入1 复制
3 5
1 1 0 0 1
0 1 1 0 1
1 1 1 1 0
6 8
1 1 0 0 1 1 1 1
0 1 1 0 1 0 1 0
1 1 1 1 0 1 1 0
0 1 1 0 0 1 0 0
1 0 1 0 0 1 0 0
0 1 0 1 0 1 1 0
样例输出1
2 3 2 1 2
3 5 4 2 2 5 4 1


这题没什么好说的


神无月排位赛
描述
《神无月》作为盛大游戏2017年的全新原创大作,其开发团队在自研实力强大的传世工作室基础之上,还有美树本晴彦等日本一线知名画师及日本游戏音乐大师崎元仁加盟参与制作。目前正在不限号内测中,有很多玩家进入到神无月的世界中。

在神无月中,有着玩家之间切磋的排位赛,其段位主要分为五大段位,从低到高依次为:新兵、菁英、战将、统帅、王者。每个玩家只有从新兵段位慢慢努力,一点点晋级才能到达王者段位。成为一个王者是每一个玩家的追求和心愿。

假设神无月的段位系统如下:

从低到高的段位依次简记为:D、C、B、A、S。玩家打排位赛,每胜利1局增加10分,输1局扣除5分。每一个段位都需要积分,累计100分才可以进入晋级赛,晋级赛采用三局两胜制(3局中达到2局胜利就晋级成功,有2局失败就算晋级失败, 连胜或连败两局,第三局不需要打了)。晋级成功后,成为下一个段位,积分变为0,重新开始算分;如果晋级失败,则积分变为60,重新开始算分。为方便计算,如果该玩家一直输,积分降为0后,不再降分,也不会掉段位。

大圣同学最近对神无月非常喜欢,一直在努力成为王者。他从新兵0分开始打排位赛(刚开始处在段位D),他告诉你最近若干场比赛的最后胜利情况,请你写个算法猜猜他现在所处的段位。当段位到达S时,段位将不再提高。


单纯的模拟,开始因为直接判断积分==100才晋级wa了一发

#include<bits/stdc++.h>
using namespace std;


int main()
{
    int n,i,dw,jf,pd0,pd1,pd2,x;
   while (~scanf("%d",&n))
   {
    dw=0; jf=0; pd0=0; pd1=pd2=0;
    for (i=1;i<=n;i++)
    {
      scanf("%d",&x);
      if (x)
      {

        if (pd0 )
        {
          pd1++;
          if (pd1==2)
          {
            pd0=pd1=pd2=0;
            dw++;
            jf=0;
          }
        }

       else if (pd0==0)
       {
         jf+=10;
         if (jf>=100 && dw<4)
         {
          pd0=1;
         }
       }
      }
      else
      {

        if (pd0)
        {
          pd2++;
          if (pd2==2)
          {
            pd1=pd2=pd0=0;
            jf=60;
          }
        }
        else
        {
          jf-=5;
          if (jf<=0) jf=0;
        }
      }
    }
    if (dw==0) printf("D\n");
    else if (dw==1) printf("C\n");
    else if (dw==2) printf("B\n");
    else if (dw==3) printf("A\n");
    else if (dw>=4) printf("S\n");
   }

}

I Love ces
描述
时间过得好快啊,SHU计算机学院又有新的一批小朋友们进来了。2016级的同学想必也是非常喜欢计算机学院的,于是院长想测试一下大家对计算机的喜爱程度(院长大人别查我水表)。

院长给大家一行由大写字母(A-Z)和小写字母(a-z)组成的字符串,允许同学们在这个字符串里面任意挑选若干个字符,问最多可以组成多少个I LOVE CES(不区分大小写,没有空格,即只要有这8个字符就可以组成一个)。

输入
多组输入,每组一行,输入一个字符串。
字符串长度<=100000。

输出
每组输出一行答案,如题意。

样例输入1 复制
IlovecesiLOVECES
样例输出1
2


很单纯的题目
统计iloveces这里的字母个数
e/2


#include <iostream>
#include <cstdio>
#include <vector>
#include <string>
#include <cstring>
#include <map>
#include <queue>
#include <algorithm>
using namespace std;

const int INF=0x3f3f3f3f;
const int maxn=1100;

//107
char ss[100010];
int a[28];
int main()
{

  int n,m,i,j;
  while (~scanf("%s",ss))
  {
   int len=strlen(ss);
   int minn=len;
   memset(a,0,sizeof(a));
   for (i=0;i<len;i++)
    {
      if ('A'<=ss[i] && 'Z'>=ss[i]) a[ss[i]-'A']++;
      else a[ss[i]-'a']++;
    }
    minn=min(minn,a['i'-'a']);
    minn=min(minn,a['l'-'a']);
    minn=min(minn,a['o'-'a']);
    minn=min(minn,a['v'-'a']);
    minn=min(minn,a['e'-'a']/2);
    minn=min(minn,a['c'-'a']);
    minn=min(minn,a['s'-'a']);
    printf("%d\n",minn);
  }

    return 0;
}

添加好友
描述
Tony最近喜欢上了龙之谷游戏,所以他想叫上他的好友组建一个公会来一起享受这款游戏。

Tony一共有n个好友,他可以叫上任意k(1<=k<=n)个好友来组建公会,并且所有好友都会答应他的请求。问Tony一共可以有多少种方案组建这个公会?

只要不是完全相同的人组建的方案视为不同方案,并且Tony至少要叫上一个人。

输入
多组输入,每组一行,输入一个正整数n(1<=n<=1000000000)。

输出
每组输出一行,输出方案数。(对1000000007取膜)

样例输入1 复制
2
样例输出1
3


单纯的数学题
从n个人里选1–n个人共有集中选法
组合数性质
Cn0+Cn1+Cn2+…+Cnn=2^n
题目求2^n-1 快速幂求解
(然后我当时居然卡了快速幂,忘记怎么初始化了!!!要这脑子有何用)


#include <iostream>
#include <cstdio>
#include <vector>
#include <string>
#include <cstring>
#include <map>
#include <queue>
#include <algorithm>
using namespace std;

const int INF=0x3f3f3f3f;
const int maxn=1100;
const int MOD=1e9+7;
//108
int main()
{

  int n;
  while (~scanf("%d",&n))
  {
    long long x=2,s=1;
    while (n)
    {
      if (n&1)
      {
        s*=x;
        s%=MOD;
      }
      x=x*x;
      x=x%MOD;
      n>>=1;
    }
    s--;
    if (s<0) s=(s+MOD)%MOD;
    printf("%d\n",s);
  }

    return 0;
}

字符串进制转换
描述
Claire Redfield在龙之谷游戏的一次任务中获得了一个上了锁的宝箱,上面刻了一串由小写字母构成的字符串A和一个数字m。

经过Claire长时间研究,他发现密码是和a,m有关的。字符串A相当于一个26进制的数字,a相当于0,b相当于1…….z相当于25。然后要将这个26进制的数转化成m进制那就是这个宝箱的密码。

Claire觉得这个太简单了所以要你帮她完成。

输入
多组输入,每组一行,输入一个字符串A和一个正整数m。
字符串长度<=10,2<=m<=9。

输出
每组输出一行答案,如题意。

样例输入1 复制
b 2
样例输出1
1


送分题 转到10进制再转换到m进制就好了
坑点大概是a也就是0的情况


#include <iostream>
#include <cstdio>
#include <vector>
#include <string>
#include <cstring>
#include <map>
#include <queue>
#include <algorithm>
using namespace std;

const int INF=0x3f3f3f3f;
const int maxn=1100;

//109
char ss[15];
int a[110];
int main()
{

  int n,m,len;
  long long s,x;
  while (~scanf("%s%d",ss,&m))
  {
   len=strlen(ss);
   x=1; s=0;

   for (int i=len-1;i>=0;i--)
   {
    s+=x*(ss[i]-'a');
    x*=26;
   }
  // printf("%lld\n",s);
   n=0;
   if (s==0) printf("0");
   else
  {
         while (s)
   {
    a[++n]=s%m;
    s=s/m;
   }
   for (int i=n;i>=1;i--) printf("%d",a[i]);
  }
    printf("\n");
  }

    return 0;
}

A序列

描述
如果一个序列有奇数个正整数组成,不妨令此序列为a1,a2,a3,…,a2∗k+1(0<=k),并且a1,a2…ak+1是一个严格递增的序列,ak+1,ak+2,…,a2∗k+1,是一个严格递减的序列,则称此序列是A序列。

比如1 2 5 4 3就是一个A序列。

现在Jazz有一个长度为n的数组,他希望让你求出这个数组所有满足A序列定义的子序列里面最大的那个长度。(子序列可以不连续)

比如1 2 5 4 3 6 7 8 9,最长的A序列子串是1 2 5 4 3。

输入
多组输入,每组两行。
第一行是n,表示给的数组的长度。
第二行有n个数(int范围),即给你的数组。
1<=n<=500000。

输出
每组输入输出一行,即最长的A序列子串的长度。

样例输入1 复制
9
1 2 5 4 3 6 7 8 9
样例输出1
5


这题应用一个严格递增序列的原理
以一个数为中心
从左边严格递增个数和从右边过来严格递增个数
取min*2-1
最后求max
开始我用的是dp打算测试一下运气 果然T啦
感觉关于这个也需要熟练一下
d[x]代表x长度的序列末尾最小的数,更新这个d就能知道当前数的最长序列是多长了
放一发学习链接:http://www.cnblogs.com/itlqs/p/5743114.html


#include <iostream>
#include <cstdio>
#include <vector>
#include <string>
#include <cstring>
#include <map>
#include <queue>
#include <algorithm>
using namespace std;

const int INF=0x3f3f3f3f;
const int maxn=50010;

//110
int a[maxn],l[maxn],r[maxn],d[maxn];
int main()
{

  int n,i,j,maxx,len;

  while (~scanf("%d",&n))
  {
    for (i=1;i<=n;i++) scanf("%d",&a[i]);
    d[1]=a[1]; len=1; l[1]=1;
    for (i=2;i<=n;i++)
    {
        if (a[i]>d[len]) { d[++len]=a[i]; l[i]=len; }
        else
        for (j=1;j<=len;j++)
            if (d[j]>=a[i]) {d[j]=a[i]; l[i]=j; break; }
    }
  //  for (i=1;i<=n;i++) printf("%d ",l[i]); printf("\n");
    r[n]=1; d[1]=a[n]; len=1;
    maxx=1;
    for (i=n-1;i>=1;i--)
    {
        if (a[i]>d[len]) { d[++len]=a[i]; maxx=max(maxx,min(l[i],len)*2-1); }
        else
       for (j=1;j<=len;j++)
            if (d[j]>=a[i]) {d[j]=a[i]; maxx=max(maxx,min(l[i],len)*2-1); break; }
    }
   // for (i=1;i<=n;i++) printf("%d ",r[i]); printf("\n");
    printf("%d\n",maxx);
  }

    return 0;
}

战斗

描述
最近,盛大计划开发一款手游,以下是简化版。系统和我方各有n头怪兽,每一头怪兽都有生命值和攻击力,并且当怪兽A攻击怪兽B,如果怪兽B的生命值高于怪兽A的攻击力,则怪兽B的生命力减少A的攻击力的数值,否则怪兽B将死亡。我方已经通过一些手段得知了系统怪兽的出战序列,我方想要知道,我方是否可以合理安排怪兽的出战序列,保证当系统的n头怪兽全部死亡时,而我方至少还存在一头怪兽。

所有怪兽是每秒攻击一次,即如果A和B战斗,A受到B的伤害的同时,B也受到A的伤害,直到一方死亡,换序列中的下一个怪兽,继续战斗。

输入
第一行一个整数T,表示测试组数。
对于每组数据,第一行输入一个整数n,1<=n<=10, 表示怪兽的数目。
接下来n行,表示系统n头怪兽的出战序列,每一行两个整数v,a, 1<=v<=1000, 1<=a<=100. 其中v表示生命值,a表示攻击力。
接下来n行,表示我方n头怪兽,但是出战序列可以由我方自己安排。每行两个整数,含义类似。

输出
每组数据输出一行。如果我方可以通过合理安排怪兽的出战序列,保证当系统的n头怪兽全部死亡,而我方至少还存在一头怪兽,那么输出YES;否则输出NO

样例输入1 复制
2
2
5 4
4 3
3 2
5 4
2
5 4
4 3
3 2
5 5
样例输出1
NO
YES


这道题,当时我觉得就是单纯的dfs
但是与error500大战了很久之后我已经没有生命值写题
更不用说打怪兽了
思路也很清楚
就是全排列己方所有的怪兽和对方互殴
不管哪一方生命值少了就换下一只怪兽
为了思路清晰写的长了一点。。懒得改了


#include<bits/stdc++.h>
using namespace std;
int v1[15],a1[15],v2[15],a2[15],vis[15];
int n;
bool flag;
void dfs(int df,int vx,int ax,int now,int vy,int ay)
{
 int x1,y1,i;
 if (flag) return;
    //printf("now=%d flag=%d\n",now,flag);
    while (vx>0 && vy>0)
    {
        vx-=ay; vy-=ax;
    }
    //printf("vx=%d,vy=%d\n",vx,vy);

    if (vx<=0 && vy<=0)
    {
         x1=df+1; y1=now+1;
         if (x1>n && y1<=n) {flag=true; return;}
         else
            for (i=1;i<=n;i++)
            if (!vis[i])
         {
             vis[i]=1;
             dfs(x1,v1[x1],a1[x1],y1,v2[i],a2[i]);
             vis[i]=0;
         }
    }
    else if (vx<=0 && vy>0)
    {
        x1=df+1;
         if (x1>n && y1<=n) {flag=true; return;}
         else  dfs(x1,v1[x1],a1[x1],now,vy,ay);
    }
    else if (vx>0 && vy<=0)
    {
         y1=now+1;
            for (i=1;i<=n;i++)
            if (!vis[i])
         {
             vis[i]=1;
             dfs(df,vx,ax,y1,v2[i],a2[i]);
             vis[i]=0;
         }
    }
    return;
}

int main()
{
    int cases,i;
   while (~scanf("%d",&cases))
   {
     while (cases--)
     {
        scanf("%d",&n);
        for (i=1;i<=n;i++) scanf("%d%d",&v1[i],&a1[i]);
        for (i=1;i<=n;i++) scanf("%d%d",&v2[i],&a2[i]);
        memset(vis,0,sizeof(vis));
        flag=false;
        for (i=1;i<=n;i++)
            if (!flag)
        {
            vis[i]=1;
            dfs(1,v1[1],a1[1],1,v2[i],a2[i]);
            vis[i]=0;
        }
      //  printf("%d\n",flag);
        if (flag) printf("YES\n"); else printf("NO\n");
     }
   }

}

调和序列


描述
给定一个长度为n的非负整数序列,下标为0,1,…,n−1.

定义:sequence(K): 由下标为K的倍数组成的子序列,即下标为0,K,2K,…,[n−1/k]∗k

query(K,S): 询问sequence(K)中的第S大的数字

输入
第一行一个整数T,表示测试组数。
对于每组数据,第一行输入两个整数n,m,1<=n<=20000, 1<=m<=100000,n表示序列的长度,m表示询问个数。
接下来一行是n个整数a0,a1,..,an−1,0<=ai<231, i=0,1,…,n−1,表示序列。
接下来m行,每行两个整数K,S


这题我没有一点思路……
一脸懵逼,放弃挣扎
赛后问hzz,他说放进vector里排序……A掉了
(还有这种操作???)不知道正解是啥


#include<bits/stdc++.h>
using namespace std;

vector<int>G[20010];
int main()
{
    int cases,i,j,x,n,m,K,S,len;
  while (~scanf("%d",&cases))
   {
     while (cases--)
     {
        scanf("%d%d",&n,&m);
        G[0].clear();
        for (i=0;i<n;i++)
        {
            G[i+1].clear();
            scanf("%d",&x);
            G[1].push_back(x);

        }
        G[0].push_back(G[1][0]);
        for (i=2;i<n;i++)
         {for (j=0;j<n;j+=i) G[i].push_back(G[1][j]);  sort(G[i].begin(),G[i].end()); }
        sort(G[1].begin(),G[1].end());
        while (m--)
        {
            scanf("%d%d",&K,&S);
            if (K>=n && S==1) printf("%d\n",G[0][0]);
            else if (K>=n) printf("-1\n");
            else
            {len=G[K].size();
                        if (len<S) printf("-1\n");
                        else printf("%d\n",G[K][len-S]);}
        }
     }
   }

}

丢史蒂芬妮
描述
有一天,空和白很无聊,决定玩盛大游戏,考虑到两个人玩,他们随便掏了一个游戏出来:在一个n∗m的棋盘上,首先把史蒂芬妮·多拉放在左上角(1,1)的位置。每次一个人可以将她往下,往右,往右下丢一格。当前回合,谁不能丢史蒂芬妮,谁就输了。(注意,不可以把活人丢出棋盘啦!)游戏总是空先手。

白说,这是一个垃圾游戏!我们每次把史蒂芬妮丢素数个位置吧!(换句话说,每次丢2或3或5或7或…格)空答应了。

我们都知道,空和白都很聪明,不管哪方存在一个可以必胜的最优策略,都会按照最优策略保证胜利。

玩了一局,空已经知道了这个游戏的套路,现在他决定考考你,对于给定的n和m,空是赢是输?如果空必胜,输出“Sora”(无引号);反之,输出“Shiro”(无引号)。


看到这题的时候
我觉得就是sg!但是我不会……一直学不动,寄希望于未来的队友会
然后就傻逼了
今天恶补了下
起码知道了怎么套路,仔细理解应该要到以后了
传送门:http://blog.csdn.net/dsaitou/article/details/74923065


不过sg最大怎么判断…这边随便写了个500*2……虽然是a了但是……

btw:NO GAME NO LIFE!疯狂打call


#include<bits/stdc++.h>
using namespace std;

int z[510],sg[510][510],vis[1030];
int main()
{
    int cases,i,j,k,n,m,x,s,len;
    bool flag;
    z[1]=2; len=1;
    for (i=3;i<=500;i++)
        {
            flag=true;
            for (j=2;j*j<=i;j++)
            if (i%j==0) {flag=false; break;}
         if (flag) z[++len]=i;
        }

    sg[1][1]=0;
    for (i=1;i<=500;i++)
        for (j=1;j<=500;j++)
        if (!(i==1 && j==1))
        {
            memset(vis,0,sizeof(vis));
            for (k=1;k<=len;k++)
            if (i-z[k]>=1 ||j-z[k]>=1)
            {
                if (i-z[k]>=1) vis[sg[i-z[k]][j]]=1;
                if (j-z[k]>=1) vis[sg[i][j-z[k]]]=1;
                if (i-z[k]>=1 && j-z[k]>=1) vis[sg[i-z[k]][j-z[k]]]=1;
            }
            else break;
            for (k=0;k<=1000;k++)
                if (!vis[k])
                {
                    sg[i][j]=k;
                    break;
                }

        }

  while (~scanf("%d",&cases))
   {
    while (cases--)
    {
        scanf("%d%d",&n,&m);

        if (sg[n][m]) printf("Sora\n"); else printf("Shiro\n");
    }
   }

}

膜一下将带给你好运


购买装备
描述
最近盛大的一款游戏传奇世界极其火爆。游戏玩家John,想购买游戏中的装备。已知游戏的商店里有n件装备,第i件装备具有属性值ai,购买需要花费bi个金币。John想去购买这些装备,但是账号中只有m个金币,John是个很贪婪的家伙,他想购买尽可能多的装备。并且在保证购买到最多件装备的情况下,他还想让他所购买的装备当中拥有最小属性值的装备的属性值尽可能大。

输入
输入测试组数T,每组数据第一行输入整数n(1<=n<=100000)和m(1<=m<=109), 接下来有n行,第i行有两个数ai, bi(1<=ai,bi<=10000).

输出
对于每组数据,输出两个数字,第一个数字代表John最多可以购买的装备数,第二个数代表在John购买最多件装备的前提下,所购买的装备当中拥有最小属性值的装备的最大属性值(输入数据保证至少可以购买一件装备)

样例输入1 复制
1
2 4
3 2
2 3
样例输出1
1 3


在问了两个人的情况下还是想了很久才想通
我太菜了.jpg
虽然说试图用自己的脑子思考结果到最后靠的还是别人帮我撸思路……


这里写图片描述
这里写图片描述


#include<bits/stdc++.h>
using namespace std;

struct points
{
    int sx,cost;
}a[100010],b[100010];
int cmp1(const points &x, const points &y)
{
    return x.cost<y.cost;
}
int cmp2(const points &x, const points &y)
{
    return x.sx<y.sx;
}
int main()
{
 int l,r,mid,cases,i,ans,n,m,mm,s,ans2;
  while (~scanf("%d",&cases))
   {
    while (cases--)
    {
        scanf("%d%d",&n,&m);
        for (i=1;i<=n;i++)
       {
        scanf("%d%d",&a[i].sx,&a[i].cost);
        b[i]=a[i];
       }
     sort(a+1,a+n+1,cmp1);//jia ge
     mm=m; ans=0;
     for (i=1;i<=n;i++)
        if (mm>=a[i].cost)
        {
            mm-=a[i].cost;
            ans++;
        }else break;
     sort(b+1,b+n+1,cmp2);//shu xing
     l=1; r=n;
     while (l<=r)
     {
        mid=(l+r)/2;
        mm=m; s=0;
        for (i=1;i<=n;i++)
        if (mm>=a[i].cost)
        {
            if (a[i].sx>=b[mid].sx)
            {
                s++;
                mm-=a[i].cost;
            }
        }else break;
        if (s==ans){ans2=b[mid].sx; l=mid+1;  }else r=mid-1;
     }
     printf("%d %d\n",ans,ans2);
    }
   }

}

零件组装


风力观测


密码破解


随机传送迷宫


不知道什么时候有能力补完剩下的题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值