1. 程式人生 > >(補題心路)——“盛大遊戲杯”第15屆上海大學程式設計聯賽夏季賽暨上海高校金馬五校賽

(補題心路)——“盛大遊戲杯”第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最大怎麼判斷…這邊隨便寫了個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);
    }
   }

}

零件組裝

風力觀測

密碼破解

不知道什麼時候有能力補完剩下的題