第15届上海大学程序设计联赛夏季赛

来源:互联网 发布:500人企业网络搭建 编辑:程序博客网 时间:2024/06/07 23:43

A:黑白图像直方图

描述
在一个矩形的灰度图像上,每个像素点或者是黑色的或者是白色的。黑色像素点用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

#include<bits/stdc++.h>using namespace std;using LL=int64_t;const int INF=0x3f3f3f3f;int ans[101][101];int main(){    ios::sync_with_stdio(0);    cin.tie(0);    int n,m;    while(cin>>n>>m) {        memset(ans,0,sizeof(ans));        for(int i=0;i<n;i++) {            for(int j=0;j<m;j++)                cin>>ans[i][j];        }        for(int i=0;i<m;i++) {            int count=0;        for(int j=0;j<n;j++) {            if(ans[j][i]==1) count++;        }        if(i==0) cout<<count;        else cout<<" "<<count;    }    cout<<endl;    }    return 0;}

B:神无月排位赛

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

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

这里写图片描述

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

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

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

输入
有若干组数据。
每组的第一行为一个N(0

#include<bits/stdc++.h>using namespace std;using LL=int64_t;const int INF=0x3f3f3f3f;int main(){    ios::sync_with_stdio(0);    cin.tie(0);    int n,x;    while(cin>>n) {        int rank=0,sum=0;        for(int i=0;i<n;i++) {            cin>>x;            if(x==1) sum+=10;            else sum-=5;            if(sum<=0) sum=0;            if(sum>=100&&i+3<n) {                int a,b,c;                cin>>a>>b;                if(a==0&&b==0) {                    sum=60;                    i+=2;                }                else if(a==1&&b==1) {                    rank++;                    sum=0;                    i+=2;                }                else if(a==1||b==1) {                    cin>>c;                    if(c==1) {                        rank++;                        sum=0;                    }                    else if(c==0) {                        sum=60;                    }                    i+=3;                }            }            else if(sum>=100&&i+2<n) {                int a,b;                cin>>a>>b;                if(a==1&&b==1) {                    rank++;                    sum=0;                    i+=2;                }            }        }        if(rank==0) cout<<'D'<<endl;        else if(rank==1) cout<<'C'<<endl;        else if(rank==2) cout<<'B'<<endl;        else if(rank==3) cout<<'A'<<endl;        else if(rank>=4) cout<<'S'<<endl;    }    return 0;}

C :I Love ces

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

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

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

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

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

#include<bits/stdc++.h>using namespace std;using LL=int64_t;const int INF=0x3f3f3f3f;int main(){    ios::sync_with_stdio(0);    cin.tie(0);    string s;    int ans[20];    while(cin>>s) {        memset(ans,0,sizeof(ans));        for(int i=0;i<s.length();i++) {            if(s[i]=='i'||s[i]=='I') ans[0]++;            else if(s[i]=='l'||s[i]=='L') ans[1]++;            else if(s[i]=='O'||s[i]=='o') ans[2]++;            else if(s[i]=='v'||s[i]=='V') ans[3]++;            else if(s[i]=='e'||s[i]=='E') ans[4]++;            else if(s[i]=='c'||s[i]=='C') ans[5]++;            else if(s[i]=='s'||s[i]=='S') ans[6]++;        }        ans[4]/=2;        int mins=INF;        for(int i=0;i<=6;i++)            mins=min(mins,ans[i]);        cout<<mins<<endl;    }    return 0;}

D:添加好友

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

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

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

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

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

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

#include<bits/stdc++.h>using namespace std;using LL = int64_t;const int INF = 0x3f3f3f3f;const int mod=1e9+7;LL q_pow(LL x,LL n) {    LL ans=1;    while(n){        if(n&1) ans=(ans*x)%mod;        n>>=1;        x=(x*x)%mod;    }    return ans;}int main(){    LL n;    while(cin>>n) {        cout<<q_pow(2,n)-1<<endl;    }    return 0;}

E:字符串进制转换

描述
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

#include<bits/stdc++.h>using namespace std;using LL=int64_t;const int INF=0x3f3f3f3f;int main(){    ios::sync_with_stdio(0);    cin.tie(0);    string s;    int m;    LL ans[300];    while(cin>>s>>m) {        LL sum=0;        memset(ans,0,sizeof(ans));        for(int i=0;i<s.length();i++) {            sum*=26;            sum+=(LL)(s[i]-'a');        }        if(sum==0) cout<<0<<endl;        else {        int temp=0;        while(sum!=0) {            temp++;            ans[temp]=sum%m;            sum/=m;        }        for(int i=temp;i>0;i--)            cout<<ans[i];        cout<<endl;        }    }    return 0;}

F: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

#include<bits/stdc++.h>using namespace std;using LL=int64_t;const int INF=0x3f3f3f3f;const int maxn=5e4+5;int ans[maxn],ar[maxn],ax[maxn],l[maxn],r[maxn];int main(){    ios::sync_with_stdio(0);    cin.tie(0);    int n;    while(cin>>n) {        for(int i=1;i<=n;i++) cin>>ans[i];        int cnt1=1,cnt2=1;        l[1]=1,r[n]=1,ar[1]=ans[1];        for(int i=2;i<=n;i++) {            if(ans[i]>ar[cnt1]) {                ar[++cnt1]=ans[i];                l[i]=cnt1;            }            else {                int pos=lower_bound(ar+1,ar+cnt1,ans[i])-ar;                ar[pos]=ans[i];                l[i]=pos;            }        }        ax[1]=ans[n];        for(int i=n-1;i>0;i--) {            if(ans[i]>ax[cnt2]) {              ax[++cnt2]=ans[i];              r[i]=cnt2;            }            else {                int pos=lower_bound(ax+1,ax+cnt2,ans[i])-ax;                ax[pos]=ans[i];                r[i]=pos;            }        }        int sum=0;        for(int i=1;i<=n;i++)            sum=max(sum,min(2*l[i]-1,2*r[i]-1));         cout<<sum<<endl;    }    return 0;}

G:战斗

描述
最近,盛大计划开发一款手游,以下是简化版。系统和我方各有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

写了两个版本,第一个没加优化:

#include<bits/stdc++.h>using namespace std;using LL=int64_t;const int INF=0x3f3f3f3f;struct Node {    int blood,cost;}ans[20],ar[20],a[20],b[20];int cnt[11]={0,1,2,3,4,5,6,7,8,9};int n;bool judge() {    for(int i=0;i<n;i++) {        a[i]=ans[i];        b[i]=ar[cnt[i]];    }    int cnt1=0,cnt2=0;    while(cnt1<n&&cnt2<n) {        int temp=min(a[cnt1].blood/b[cnt2].cost,b[cnt2].blood/a[cnt1].cost);        a[cnt1].blood-=b[cnt2].cost*temp;        b[cnt2].blood-=a[cnt1].cost*temp;        while(a[cnt1].blood>0&&b[cnt2].blood>0) {            a[cnt1].blood-=b[cnt2].cost;            b[cnt2].blood-=a[cnt1].cost;        }        if(a[cnt1].blood<=0) cnt1++;        if(b[cnt2].blood<=0) cnt2++;    }    if(cnt1==n&&cnt2<n) return true;    else return false;}int main(){    ios::sync_with_stdio(0);    cin.tie(0);    int T;    cin>>T;    for(int k=0;k<T;k++) {        cin>>n;        for(int i=0;i<n;i++) cin>>ans[i].blood>>ans[i].cost;        for(int i=0;i<n;i++) cin>>ar[i].blood>>ar[i].cost;        int flag=0;        do {            if(judge()) {                flag=1;                break;            }        }while(next_permutation(cnt,cnt+n));        if(flag==1) cout<<"YES"<<endl;        else cout<<"NO"<<endl;    }    return 0;}

用了1869ms
然后加了下优化:

#include<bits/stdc++.h>using namespace std;using LL=int64_t;const int INF=0x3f3f3f3f;struct Node {    int blood,cost;}ans[20],ar[20],a[20],b[20];int cnt[11]={0,1,2,3,4,5,6,7,8,9};int book[11];int sum[11];int n;int nexts=0;bool judge() {    for(int i=0;i<n;i++) {        a[i]=ans[i];        b[i]=ar[cnt[i]];    }    int cnt1=0,cnt2=0;    while(cnt1<n&&cnt2<n) {        int temp=min(a[cnt1].blood/b[cnt2].cost,b[cnt2].blood/a[cnt1].cost);        a[cnt1].blood-=b[cnt2].cost*temp;        b[cnt2].blood-=a[cnt1].cost*temp;        while(a[cnt1].blood>0&&b[cnt2].blood>0) {            a[cnt1].blood-=b[cnt2].cost;            b[cnt2].blood-=a[cnt1].cost;        }        if(a[cnt1].blood<=0) cnt1++;        if(b[cnt2].blood<=0) cnt2++;    }    if(cnt1!=n&&cnt2==n) {        for(int i=0;i<cnt1;i++)            book[i]=cnt[i];        nexts=cnt1;    }    if(cnt1==n&&cnt2<n) return true;    else return false;}int main(){    ios::sync_with_stdio(0);    cin.tie(0);    int T;    cin>>T;    sum[1]=1;    for(int i=2;i<11;i++) sum[i]=sum[i-1]*i;    for(int k=0;k<T;k++) {        cin>>n;        for(int i=0;i<n;i++) cin>>ans[i].blood>>ans[i].cost;        for(int i=0;i<n;i++) cin>>ar[i].blood>>ar[i].cost;        int flag=0;        do {            int i;            if(nexts!=0) {                for(i=0;i<nexts;i++) {                    if(book[i]!=cnt[i]) break;                }                    if(i==nexts) continue;                    else {                        nexts=0;                        memset(book,0,sizeof(book));                    }            }            if(judge()) {                flag=1;                break;            }        }while(next_permutation(cnt,cnt+n));        if(flag==1) cout<<"YES"<<endl;        else cout<<"NO"<<endl;    }    return 0;}

用了87ms

H:调和序列

描述
给定一个长度为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
0

#include<bits/stdc++.h>using namespace std;using LL=int64_t;const int INF=0x3f3f3f3f;const int maxn=2e4+5;int ans[maxn];int n,m;vector<int>ar[maxn];void init() {    for(int i=1;i<n;i++) {        ar[i].clear();        for(int j=0;j<n;j+=i)        ar[i].push_back(ans[j]);    }}int main(){    ios::sync_with_stdio(0);    cin.tie(0);    int T;    cin>>T;    for(int k=0;k<T;k++) {        cin>>n>>m;        for(int i=0;i<n;i++) cin>>ans[i];        init();        int book[maxn];        memset(book,0,sizeof(book));        for(int i=0;i<m;i++) {            int k,s;            cin>>k>>s;            if(k>=n) {                if(s==1) cout<<ans[0]<<endl;                else cout<<-1<<endl;            }            else if(ar[k].size()<s) cout<<-1<<endl;            else if(book[k]==0) {                sort(ar[k].begin(),ar[k].end(),greater<int>());                book[k]=1;                cout<<ar[k][s-1]<<endl;            }            else if(book[k]==1)                 cout<<ar[k][s-1]<<endl;        }    }    return 0;}

I:丢史蒂芬妮

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

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

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

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

输入
第一行有一个T表示数组组数,1<=T<100000
从第二行开始,每行为棋盘大小,n、m分别表示行列。
1=

#include<bits/stdc++.h>using namespace std;using LL=int64_t;const int INF=0x3f3f3f3f;const int maxn=1005;int ans[505][505];int prime[100]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503};void init() {    memset(ans,0,sizeof(ans));    for(int i=1;i<=500;i++) {        for(int j=1;j<=500;j++) {            if(ans[i][j]==0) {                for(int k=0;;k++) {                    if(i+prime[k]>500&&j+prime[k]>500) break;                    if(i+prime[k]<=500) ans[i+prime[k]][j]=1;                    if(j+prime[k]<=500) ans[i][j+prime[k]]=1;                    if(i+prime[k]<=500&&j+prime[k]<=500) ans[i+prime[k]][j+prime[k]]=1;                }            }        }    }}int main(){    ios::sync_with_stdio(0);    cin.tie(0);    init();    int n,x,y;    cin>>n;    for(int i=0;i<n;i++) {        cin>>x>>y;        if(ans[x][y]==1) cout<<"Sora"<<endl;        else cout<<"Shiro"<<endl;    }    return 0;}

K:购买装备

描述
最近盛大的一款游戏传奇世界极其火爆。游戏玩家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

#include<bits/stdc++.h>using namespace std;using LL=int64_t;const int INF=0x3f3f3f3f;const int maxn=1e5+5;struct Node {    LL a,b;}ans[maxn];bool cmp(Node a ,Node b) {    return a.b<b.b;}int sum,n,m;int check(int num) {    int count=0,temp=0;    for(int i=0;i<n;i++) {        if(ans[i].a>=num) {            count++;            temp+=ans[i].b;        }        if(temp>m) break;        if(count==sum) break;    }    if(count==sum&&temp<=m) return 1;    return 0;}int main(){    ios::sync_with_stdio(0);    cin.tie(0);    int T;    cin>>T;    for(int k=0;k<T;k++) {        LL mins=INF,maxs=0;        cin>>n>>m;        for(int i=        0;i<n;i++) {            cin>>ans[i].a>>ans[i].b;            mins=min(mins,ans[i].a);            maxs=max(maxs,ans[i].a);        }        sort(ans,ans+n,cmp);        int temp=0,count=0;        sum=0;        for(int i=0;i<n;i++) {            if(ans[i].b+temp<=m) {                sum++;                temp+=ans[i].b;            }            else break;        }        while(mins<=maxs) {            int mid=(mins+maxs)/2;            if(check(mid)) {                count=mid;                mins=mid+1;            }            else maxs=mid-1;        }        cout<<sum<<" "<<count<<endl;    }    return 0;}
阅读全文
0 0
原创粉丝点击