第9届北信校赛

来源:互联网 发布:java服务器开发与c 编辑:程序博客网 时间:2024/05/20 09:23

A. paulzhou的完美算术教室

Problem Description
众所周知,paulzhou的数学不太好。现在他有一个问题,希望你帮他解答:
在二维平面上给出一些整数点,希望在这些点中找出两个距离最近的点,并且输出这两个点的距离。
Input
第1行输入T(1≤T≤100),代表有T组数据。
接下来的T行输入,每行包含一组测试数据。输入数据为一系列坐标。数据保证为严格的“(x1, y1) (x2, y2) (x3, y3) … ”格式。输入保证点的数量不超过100个。坐标均为非负整数,且不会超过100,输入字符串长度不会超过1000。
Output
每组测试数据输出一行,仅包含一个浮点数,代表最近的距离,输出保留四位小数(无需四舍五入)。
Sample Input
2
(1, 1) (2, 1) (0, 0)
(1, 1) (2, 2)
Sample Output
1.0000
1.4142

WA了好多次,我也不知道为啥
先附上AC代码:

#include<bits/stdc++.h>using namespace std;using LL=int64_t;const int maxn=1e5;struct Node {    int x,y;}node[maxn];int main(){    int T;    cin>>T;    getchar();    while(T--) {        string s;        getline(cin,s);        int temp=0;        double min_sum=1e8;        for(int i=0;i<s.length();i+=7) {            node[temp].x=s[i+1]-'0';            if(s[i+2]-'0'>=0&&s[i+2]-'0'<=9) {node[temp].x=10*node[temp].x+s[i+2]-'0';i++;}            if(s[i+2]-'0'>=0&&s[i+2]-'0'<=9) {node[temp].x=10*node[temp].x+s[i+2]-'0';i++;}            node[temp].y=s[i+4]-'0';            if(s[i+5]-'0'>=0&&s[i+5]-'0'<=9) {node[temp].y=10*node[temp].y+s[i+5]-'0';i++;}            if(s[i+5]-'0'>=0&&s[i+5]-'0'<=9) {node[temp].y=10*node[temp].y+s[i+5]-'0';i++;}            temp++;        }        for(int i=0;i<temp;i++) {            for(int j=i+1;j<temp;j++) {                 double ans_temp=((node[j].x-node[i].x)*(node[j].x-node[i].x))+((node[j].y-node[i].y)*(node[j].y-node[i].y));                ans_temp=sqrt(ans_temp);                if(ans_temp<min_sum) min_sum=ans_temp;            }        }        printf("%.4f\n",min_sum);    } return 0;}

后来找到,我以为printf里面的%.4f会四舍五入,后来把四舍五入的判断删了就过了…..玄学题……

B. An easy problem

Problem Description
萌老师给Anonymous布置了数据结构课设作业――计算机博弈,Anonymous十分苦恼,于是她在纸上画棋盘来找灵感。这时她发现有一只蚂蚁落入了其中一个棋格里,现有一行只包括(U、D、L、R)四种字符的命令,U为上、D为下、L为左、R为右,现在Anonymous想知道这个命令中有多少子串(包括自身)能使蚂蚁回到原点。
Input
第一行输入一个整数T,表示测试实例的数量;
对于每个实例,输入一个整数n(1<=n<=200),表示命令的长度,再输入一行长度为n仅包含(U、D、L、R)的字符串。
Output
对于每个实例,输出一个整数,表示满足要求的子串的数量。
Sample Input
1
6
URLLDR
Sample Output
2

长度小,直接暴力,画个图,走过的标记一下,如果再次走到这里,就是走了个环或者来回走,就是一个可以回到原点的子串

附上AC代码:

#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 T;    cin>>T;    while(T--){        int len;        string s;        cin>>len>>s;        int sum=0;        int ans[105]={0};        for(int i=0;i<len;i++) {            if(s[i]=='U') ans[i]=1;            else if(s[i]=='D') ans[i]=-1;            else if(s[i]=='L') ans[i]=1000;            else if(s[i]=='R') ans[i]=-1000;        }        for(int i=0;i<len;i++) {                int temp=0;            for(int j=i;j<len;j++) {                temp+=ans[j];                if(temp==0) sum++;            }        }        cout<<sum<<endl;    }    return 0;}

C. 善良的XLAOSHI

Problem Description
生活在上古世界亡灵岛的小白就快到亡灵岛上的期末考试了,可是小白却没有任何准备。于是小白只能靠自己的运气来决定自己的生死了,而亡灵岛的其中一个侍者XLAOSHI十分善良,他决定只要小白有存活的希望就让他活下来。
小白一共有n场考试,分散在n天中,即一天有且仅有一场,只有他当天的运气不小于考试的难度才能够通过考试,而小白只有通过所有的考试才能存活下来,生活如此艰难~~~
现在XLAOSHI运用自己的通天能力得知了小白在未来的m天中每天的运气值ai,他希望从中取出n天的运气来让小白通过考试,XLAOSHI取出来的n天的运气可以重新安排次序,来使小白的运气充分使用,但是不能改变某天的运气值的大小。例如有三天的运气按照时间先后依次是100,200,300,XLAOSHI可以将它调整为这三个数的任意排列顺序。
上帝视角的你看到了这一幕,于是你决定在梦中启示小白的命运。
Input
测试数据第一行为测试样例总组数T,
每组数据有三行,
第一行为正整数n,m(1<=n,m<=30000)。
第二行为n个整数,用空格隔开,即n天中每场考试的难度。
第三行为m个整数,用空格隔开,即小白m天的运气。
Output
对于每组数据,如果小白能够活下来,输出“You are pretty lucky!”;否则输出“Time up!”;
Sample Input
2
2 3
5 4
7 8 4
2 1
5 5
10
Sample Output
You are pretty lucky!
Time up!

排个序直接从小到大比就行,如果考试难度大于运气,就退出
附上AC代码:

#include<bits/stdc++.h>using namespace std;using LL=int64_t;const int INF=0x3f3f3f3f;const int maxn=3e4+6;int ans[maxn],ar[maxn];int main(){    ios::sync_with_stdio(0);    cin.tie(0);    int T;    cin>>T;    while(T--) {        memset(ans,0,sizeof(ans));        memset(ar,0,sizeof(ar));        int n,m;        cin>>n>>m;        for(int i=0;i<n;i++)            cin>>ans[i];        for(int i=0;i<m;i++)            cin>>ar[i];        sort(ans,ans+n,greater<int>());        sort(ar,ar+m,greater<int>());        int flag=0;        for(int i=0;i<n;i++) {            if(ar[i]<ans[i]) {flag=1;break;}        }        if(flag==0) cout<<"You are pretty lucky!"<<endl;        else cout<<"Time up!"<<endl;    }    return 0;}

D. 环游四边形

Problem Description
一天傍晚,吃过饭的小白正在骑小黄车漫游傍晚的京城,突然他看到了一个类似C60结构的正60面体结构的建筑物。他突然脑冻大开想到:假如他在这个正六面体围成的的三维空间中的某一点位置上,如果他想要骑车(将小白视为质点)触碰到这个正六十面体的每一个面至少一次并在最后再回到出发位置最少需要骑多长的路程,小白可以按照任意的路径在这个空间中行走。但这个问题对于小白来说太难了,他决定先尝试考虑一个简单的问题来从中获得启发,他需要你帮他考虑在二维平面空间中的情况,即在边长为a的正方形内部中的某个点(x,y)到达四条边至少一次并回到原来位置的最少路程是多少,正方形的左下角坐标为(0,0),小白会非常感谢你的帮助~
这里写图片描述
使用double,不要用float
Input
数据第一行为测试样例总组数T,
每组数据只包含一行,其中有三个整数a,x,y用空格隔开。(0

#include<bits/stdc++.h>using namespace std;using LL=int64_t;const int INF=0x3f3f3f3f;int main(){    int T;    cin>>T;    while(T--) {        double a,x,y;        cin>>a>>x>>y;        printf("%.6f\n",2*a*sqrt(2));    }    return 0;}

E. 一道很水很水很水的签到题

Problem Description
还描述啥啊, 这道题太水了。。。。。。请输出”ya mie die”(引号内的内容)。注:输出后要换行。
Input

Output
ya mie die
Sample Input

Sample Output
ya mie die
附上AC代码:

#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);    cout<<"ya mie die"<<endl;    return 0;}

F. Make Anonymous be the lucky guy

Problem Description
近来,校队队员都感到无比无聊,除了每天刷题之外,没有事情可以提高幸福指数,于是队内的PaulZhou决定带领大家做游戏,校队一共有n名队员,每个人选择一个0至100的数字,所选数字小于等于所有数字的平均值的3/4并最接近者获胜,若此时有多个人满足获胜条件则随机抽取一位定为获胜者。
由于最近Anonymous沉迷于数据结构作业无法自拔,导致她运气极差,已经连输多场,PaulZhou为了照顾她的情绪决定偷偷给她看所有人选择的数字。
Anonymous喜欢大数字并且不想让人知道她作弊,由于她最近写数据结构作业傻掉了,所以你需要帮助Anonymous选择出一个可能获胜的最大数字,并计算出获胜的概率。
Input
第一行输入一个整数T(T<=10),表示测试实例的个数;
接下来对每个实例,先输入一个整数n(n<=100),表示校队的人数,接下来输入n-1个数,表示除Anonymous以外,其他人选择的数字。
Output
对于每组实例,输出一个整数――表示Anonymous选择的数字,以及Anonymous获胜的概率,保留两位小数。
Sample Input
2
5
1 2 3 4
4
1 1 2
Sample Output
1 0.50
0 1.00

暴力从大到小搜啊
附上AC代码:

#include<bits/stdc++.h>using namespace std;using LL=int64_t;const int INF=0x3f3f3f3f;int main(){    int T;    cin>>T;    while(T--) {        int n,x;        cin>>n;        int ans[105]={0},sum_all=0;        for(int i=1;i<n;i++) {            cin>>x;            ans[x]++;            sum_all+=x;        }        int win_num=0;        for(int i=100;i>=0;i--) {            double sum=(double)(sum_all+i)/n;            if(i<=sum*0.75) {win_num=i;break;}        }        printf("%d %.2f\n",win_num,1.0/(ans[win_num]+1));    }    return 0;}

G. 当然选择原谅她呀

Problem Description
小陈和小白是一对恩爱的夫妻, 可是有一天小白被困在了大魔王小张的手里, 小张将小白困在了迷宫的最右下角,于是小陈打算从迷宫的左上角出发去找到她并且原谅她呀!
Input
输入文件将包含一组或者几组数据。每组测试数据包含一个n, m(0 < n,m <= 20)表示迷宫的行数和列数。紧跟着一个n行m列的矩阵表示一个迷宫, 其中的1表示墙壁,0表示可以走的路, 只能横着走或者竖着走, 不能斜着走, 要求编程序找出从左上角到右下角最短路径的步数。
Output
左上角到右下角最短路径的步数。如果小陈没办法原谅小陈, 输出”-1”
Sample Input
5 5
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
Sample Output
8

dfs搜一下就好了,经典题目
附上AC代码:

#include<bits/stdc++.h>using namespace std;using LL=int64_t;const int INF=0x3f3f3f3f;int ans[21][21],book[21][21];int sum=0,n,m;int cnt[4][2]={1,0,-1,0,0,1,0,-1};int flag=INF;void dfs(int temp,int x,int y) {    if(temp>5*sum) return ;    if(x==n-1&&y==m-1) {flag=min(flag,temp);return ;}    for(int i=0;i<4;i++) {        int temp_x=x+cnt[i][0];        int temp_y=y+cnt[i][1];        if(temp_x>=0&&temp_x<n&&temp_y>=0&&temp_y<m&&book[temp_x][temp_y]==0&&ans[temp_x][temp_y]==0) {            book[temp_x][temp_y]=1;            dfs(temp+1,temp_x,temp_y);            book[temp_x][temp_y]=0;        }    }}int main(){    ios::sync_with_stdio(0);    cin.tie(0);    while(cin>>n>>m) {            sum=0,flag=INF;        memset(book,0,sizeof(book));        for(int i=0;i<n;i++) {            for(int j=0;j<m;j++) {                cin>>ans[i][j];                if(ans[i][j]==0) sum++;            }        }    book[0][0]=1;    dfs(0,0,0);    if(flag==INF||sum==0) cout<<-1<<endl;    else cout<<flag<<endl;    }    return 0;}

I. paulzhou的数学?TAT?

Problem Description
众所周知,paulzhou的数学不太好。现在他有一个问题,希望你帮他解答:
定义这里写图片描述,求最小的正整数y使得这里写图片描述,其中这里写图片描述
Input
第一行输入一个整数T(T<=10),表示测试实例的数量;
每组用例输入一个非负整数n(n<10^100)
Output
对于每组用例,如果y<=5则输出y,否则输出“TAT”
Sample Input
2
233
233333333333333333333333333333333333333333333333333333333
Sample Output
3
TAT

本来很简单的题目,用字符串输入判断一下就好了,结果第一次用大数模板给wa了,看来模板还需要改改
开五次根如果是1就输出,否则TAT,而且手下你判断一下字符串长度,因为如果开5次根能开出来且向下取整==1,原数肯定小于2^32次方,长度肯定小于11
附上AC代码:

#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 T;    cin>>T;    while(T--) {        string s;        cin>>s;        if(s.length()>11) cout<<"TAT"<<endl;        else {            LL ans=0;            for(int i=0;i<s.length();i++)                ans+=(s[i]-'0')*pow(10,s.length()-i-1);            int temp=0;            while(temp<6) {                ans=sqrt(ans);                temp++;                if(ans==1) break;            }            if(ans==1) cout<<temp<<endl;            else cout<<"TAT"<<endl;        }    }    return 0;}

J. 小可爱

Problem Description
小可爱推了推眼镜表示很不开心, 她最近在玩一个字符消除游戏。给定一个只包含大写字母”ABC”的字符串s,消除过程是如下进行的:

1)如果s包含长度超过1的由相同字母组成的子串,那么这些子串会被同时消除,余下的子串拼成新的字符串。例如”ABCCBCCCAA”中”CC”,”CCC”和”AA”会被同时消除,余下”AB”和”B”拼成新的字符串”ABB”。

2)上述消除会反复一轮一轮进行,直到新的字符串不包含相邻的相同字符为止。例如”ABCCBCCCAA”经过一轮消除得到”ABB”,再经过一轮消除得到”A”

游戏中的每一关小可爱都会面对一个字符串s。在消除开始前小可爱有机会在s中任意位置(第一个字符之前、最后一个字符之后以及相邻两个字符之间)插入任意一个字符(‘A’,’B’或者’C’),得到字符串t。t经过一系列消除后,小可爱的得分是消除掉的字符的总数。

小可爱知道只有努力努力再努力才能获得最高得分, 但是小可爱实在是太蠢萌了, 于是找到聪明的你来帮助她解决这个问题。
Input
输入第一行是一个整数T(1<=T<=100),代表测试数据的数量。
之后T行每行一个由’A”B”C’组成的字符串s,长度不超过100。
Output
对于每一行输入的字符串,输出小可爱最高能得到的分数。
Sample Input
3
ABCBCCCAA
AAA
ABC
Sample Output
9
4
2
这是一道hihoCoder上的原题,有种消消乐的感觉,做法也是直接暴力,因为给的范围很小
附上AC代码:

#include<bits/stdc++.h>using namespace std;using LL=int64_t;const int INF=0x3f3f3f3f;char cnt[]="ABC";string s;string check(string temp) {    int len=temp.length();    if(len<=1) return temp;    string ar="";    for(int i=0;i<len-1;i++) {        if(temp[i]==temp[i+1]) {            while(i+1<len&&temp[i]==temp[i+1]) i++;        }        else ar+=temp[i];    }    if(temp[len-2]!=temp[len-1]) ar+=temp[len-1];    return ar;}int main(){    int T;    cin>>T;    while(T--) {        cin>>s;        int sum=0;        for(int i=0;i<s.length();i++) {            for(int j=0;j<3;j++) {                string temp=s.substr(0,i+1)+cnt[j]+s.substr(i+1);                int len=temp.length();                temp=check(temp);                while(len>temp.length()) {                    len=temp.length();                    temp=check(temp);                }                int sums=s.length()-temp.length()+1;                sum=max(sum,sums);                temp=s;            }        }        cout<<sum<<endl;    }    return 0;}

就是从头开始每个地方吧A,B,C分别插进去,判断最后的剩下的个数,暴力枚举的一道题….不看题解我还真想不出这么暴力的解法….

H. paulzhou和他的学弟们

Problem Description
众所周知,paulzhou的数学不太好。现在他有一个问题,希望你帮他解答:
paulzhou有一堆颜值很高的学弟,每一个学弟有一个颜值。他希望在这一堆学弟中找出n(1≤n≤1000)个学弟,使这些学弟的颜值分别为ai(1≤i≤n,1≤ai≤1000)。

paulzhou首先从一堆学弟中找出颜值总和为∑ai(1≤i≤n)的学弟,代价为paulzhou的颜值。由于召集一堆学弟很麻烦,所以这个操作只允许做一次。

接下来,paulzhou可以从选出的一小堆学弟中,选出指定颜值的学弟或者选出一小小堆学弟,代价为paulzhou的颜值k和这一小堆学弟的颜值和。

paulzhou是一个精通「まほう」的人,因此他可以将选出的一小堆学弟中的颜值任意分配。

paulzhou希望知道自己找到所有指定颜值的学弟的最小代价,“找出”指的是学弟必须单独地站在paulzhou面前,而不是在一小堆或一堆中。
Input
第1行输入T(1≤T≤100),代表有T组数据。
接下来的T行输入,每行包含一组测试数据。每组测试数据第一行包含两个正整数n(1≤n≤1000),k(1≤k≤100000000),分别代表paulzhou希望找到的学弟数量和paulzhou的颜值;第二行包含n个正整数ai(1≤i≤n,1≤ai≤1000),分别代表每一个学弟的颜值。
Output
每组测试数据输出一个正整数,代表paulzhou达到目的的最小代价。
Sample Input
2
3 100
1 2 3
5 100
1 2 3 4 5
Sample Output
309
533

题意杀,看不懂题就算了….我也不知道出题人想干嘛….总之就是建造一个哈夫曼树,计算从底到顶的最小费用,知道这些就好说了
附上AC代码:

#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 T;    cin>>T;    while(T--) {        LL n,k;        cin>>n>>k;        priority_queue<LL> ans;        for(LL i=0;i<n;i++) {            LL x;            cin>>x;            ans.push(-x);        }        LL sum=0;        while(ans.size()!=1) {            LL temp=ans.top();            ans.pop();            temp+=ans.top();            ans.pop();            sum+=temp;            ans.push(temp);        }        ans.pop();        if(n!=1) cout<<sum*(-1)+n*k<<endl;        else cout<<sum*(-1)+k<<endl;    }    return 0;}

用一个priority_queue直接解决,不过注意最后要特判一下是n==1的情况,因为是1的话,就不用找到他的费用了。而且是从小到大排,用个-号就解决了。