2017年“达内杯”台州学院第十届大学生程序设计竞赛 非官方题解
Posted BobHuang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2017年“达内杯”台州学院第十届大学生程序设计竞赛 非官方题解相关的知识,希望对你有一定的参考价值。
感谢crq兄弟搞了这次校赛,让我认识到了自己傻的时候确实傻的可爱。crq棒棒哒,我们OJ也十年多了,不容易啊。大家能用得上的时候确实要练好基本功啊。
5259: 多项式值统计
Total Submit: 316 Accepted:35
Description
形如anxn+an-1xn-1+…+a2x2 +a1x +a0的多项式称为一元多项式,现给出若干个一元多项式,以及x的值,请统计出:
(1)所有多项式的最大值;
(2)根据多项式值是否相同进行分组,相同值分为一组,不同值不同组,问组内多项式最多的组有多少个多项式?
Input
输入数据有多组。
第一行为数据组数t。
接下来有t组数据,每组数据的第一行为两个整数n(2<=n<=100)和x(绝对值不超过10),表示多项式的个数和多项式中x的取值。
接下来有n行,每行表示一个一元多项式,每个多项式先给出非零项的个数,再以指数递降方式输入一个多项式非零项系数(绝对值不超过10的整数)和指数(不超过10的非负整数)。
Output
每组输出一行,包含两个整数,分别为多项式的最大值和组内多项式最多的组所对应的多项式个数。
Sample Input
1
3 1
2 2 1 1 0
1 3 1
1 4 1
Sample Output
4 2
这道也是水题吧,求出给定多项式的值,但是有个小细节,就是多项式的值可能是负数。map一下,建立键值就好了哇。
#include <iostream> #include <algorithm> #include <map> using namespace std; int main() { int t; while(cin>>t){ while(t--){ __int64 n,x; cin>>n>>x; __int64 ma1=-1<<30; map<__int64,int>ma; while(n--){ __int64 m; cin>>m; __int64 ma2=0; for(__int64 i=0;i<m;i++){ __int64 a,b; cin>>a>>b; __int64 s=a; for(__int64 j=0;j<b;j++) s*=x; ma2+=s; } ma[ma2]++; ma1=max(ma2,ma1); } printf("%lld",ma1); map<__int64,int>::iterator it; int ma2=0; for(it=ma.begin();it!=ma.end();it++){ ma2=max(ma2,it->second); } printf(" %d\\n",ma2); ma.clear(); }} return 0; }
5260: 排列
总提交: 83 测试通过:16
描述
从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。当m=n时所有的排列情况叫全排列。
比如有4个元素:1 3 4 6
其全排列为:
1 3 4 6
1 3 6 4
1 4 3 6
1 4 6 3
1 6 3 4
1 6 4 3
3 1 4 6
3 1 6 4
3 4 1 6
3 4 6 1
3 6 1 4
3 6 4 1
4 1 3 6
4 1 6 3
4 3 1 6
4 3 6 1
4 6 1 3
4 6 3 1
6 1 3 4
6 1 4 3
6 3 1 4
6 3 4 1
6 4 1 3
6 4 3 1
现在从中任选一个排列,比如
3 6 1 4
然后不断地取下一个排列组成一个新的序列,当取到最后一个排列时重新回到第一个排列取,由此反复循环形成了一个无限长的序列:
3 6 1 4 3 6 4 1 4 1 3 6......
现在的问题是,这个序列的第x个元素是什么?
输入
输入数据有多组(不大于100组),每组占2行,第一行为两个正整数n和x,n和x的含义见描述(x<=1000000000,n<=5)。
接下来一行包含n个互不相同的正整数,表示全排列中任选的一个排列,并以此作为新序列的起始元素。
输出
每组输出一个正整数,表示第x个元素值。
样例输入
4 5
3 6 1 4
样例输出
3
第二题也是水题啊,自己一直错,好气哦,就是全排列找下第n个值啊,真是对自己无语了,进行了两次全排列就TLE真是醉了,这个函数的定义是这样的
在当前序列中,从尾端往前寻找两个相邻元素,前一个记为*i,后一个记为*ii,并且满足*i < *ii。然后再从尾端寻找另一个元素*j,如果满足*i < *j,即将第i个元素与第j个元素对调,并将第ii个元素之后(包括ii)的所有元素颠倒排序,即求出下一个序列了。
#include <stdio.h> #include <algorithm> int has[100000]; using namespace std; int main() {int n,x; while(~scanf("%d%d",&n,&x)){ int b[10]={0}; int a[10]={0}; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); b[i]=a[i];} sort(b+1,b+n+1); int s1=0,f=0; int ac=0; int s=n; for(int i=2;i<=n;i++) s*=i; for(int i=0;i<s/n;i++){ if(a[1]==b[1]&&a[2]==b[2]&&a[3]==b[3]&&a[4]==b[4]) ac=1; else if(ac!=1)s1++; for(int j=1;j<=n;j++) has[f++]=b[j]; next_permutation(b+1,b+n+1);} x=x+s1*n; x%=s; if(x!=0)x-=1; printf("%d\\n",has[x]); } return 0; }
5263: 小朋友们的游戏
总提交: 79 测试通过:7
描述
yuyu和小朋友们在操场上玩游戏,互相之间需要通话,如果距离太远,小朋友们就想办法让附近的人帮忙转达一下。现在已知两个小朋友之间直接通话所需要的音量等于他们之间距离的平方,问只要小朋友发出最少多大的音量就能保证互相之间都能够通话。
输入
输入数据有多组,每组数据的第一行为正整数N(1<=N<=1000),表示小朋友的数量,接下来有N行,每行两个整数x和y,表示小朋友所在的坐标值,坐标值绝对值小于25000。
输出
每组输出一个整数,表示所需要的音量。
样例输入
4
1 0
2 0
0 1
1 3
样例输出
5
最小生成树,找到最长的权值,这个为什么会正确呢,因为要两两最短,所以这个生成树的的值也是最小。这个有个坑,就是要用prime算法,边太多了,用Kruskal算法复杂度太高会过不了的
当时没带模版,打不出来啊
#include<iostream> using namespace std; #define MAX 1005 #define MAXCOST 0x7fffffff int graph[MAX][MAX]; int x1[MAX],y1[MAX],mi; int prim(int graph[][MAX], int n) { int lowcost[MAX]; int mst[MAX]; int i, j, min, minid, sum = 0; for (i = 2; i <= n; i++) { lowcost[i] = graph[1][i]; mst[i] = 1; } mst[1] = 0; for (i = 2; i <= n; i++) { min = MAXCOST; minid = 0; for (j = 2; j <= n; j++) { if (lowcost[j] < min && lowcost[j] != 0) { min = lowcost[j]; minid = j; } } mi=max(mi,min); sum += min; lowcost[minid] = 0; for (j = 2; j <= n; j++) { if (graph[minid][j] < lowcost[j]) { lowcost[j] = graph[minid][j]; mst[j] = minid; } } } return mi; } int main() { int i, j, k, l, m, n; int x, y, cost; while(cin >> n){ mi=0; for (i = 1; i <= n; i++) { for (j = 1; j <= n; j++) { graph[i][j] = MAXCOST; } } for(k = 1; k <= n; k++){ cin>>x1[k]>>y1[k]; for(l=1;l<k;l++) { cost=(x1[l]-x1[k])*(x1[l]-x1[k])+(y1[l]-y1[k])*(y1[l]-y1[k]); graph[k][l] = cost; graph[l][k] = cost; } } cost = prim(graph, n); cout <<mi << endl;} return 0; }
5264: 买张公交卡吧
总提交: 408 测试通过:55
描述
crq是个无车一族,不过坐公交车可以打一个盹也不错,最近听说刷公交卡能打6折,还可以在1小时内免费换乘车1次(也就是在你上次刷卡付费后不超过1小时可以免费1次,但如果前一次免费则本次刷卡就不能免费了)。
现在给出crq一天以内的坐车情况,问这一天共消费了多少元。
假设公交车原价都是2元,而且每次都是刷卡消费,题目保证卡内余额充足。
输入
输入数据有多组,每组数据的第一行为正整数n(n<=10),表示乘坐的公交车趟数,接下来有n行,每行包括一个时间(格式hh:mm:ss),时间均在同一天内24小时制,而且已经按照时间先后排序。
输出
每组输出一个小数,表示总共消费金额,保留1位小数。
样例输入
3
12:00:00
12:30:00
12:50:00
样例输出
2.4
就是我标记下这次之前的有没有享受一小时内换乘优惠,还有这次和上次的时间差在不在范围内
crq这个来源于生活啊,台州公交是这样的,临海并不这样啊
#include <stdio.h> int main() {int t; while(~scanf("%d",&t)){ int h,m,s; int sum=0,f=0,t2=0; while(t--){ scanf("%d:%d:%d",&h,&m,&s); int t1=h*3600+m*60+s; if(t1-t2<=3600&&f==0){ f=1; } else{ sum+=2; f=0; } t2=t1;} printf("%.1f\\n",sum*0.6); } return 0; }
5265: 围棋入门
总提交: 139 测试通过:22
描述
YuYu最近开始学习围棋,爸爸先传授她第一个入门基础就是在哪些位置落子能够将对方围住。
现在给定棋盘某个状态,轮到黑方落子(围棋规定黑方先下,YuYu总是先下的),若要将白棋围住,需要在哪些位置落子呢,请将它们全部找出来。
围棋棋盘由19*19的方格组成,每个交叉点坐标为(i, j),其中1<=i<=19, 1<=j<=19。
输入
输入数据有多组,每组数据包括19行,每行19个字符,其中:
(1).表示空白位置;
(2)B表示黑色棋子
(3)W表示白色棋子。
输出
每组输出若干行,每行两个正整数,表示可以落子的交叉点坐标值,按照行号从小到大的顺序输出,如果行号相同,则按照列号从小到大的顺序输出。
如果白方已经被围住,输出YuYu Wins!
样例输入
...................
...................
...................
...................
...................
........BW.........
...................
...................
...................
...................
...................
...................
...................
...................
...................
...................
...................
...................
...................
样例输出
5 10
6 11
7 10
没想到这个题竟然是这种简单的暴力,枚举所有白棋,如果是\'.\'就可以放黑棋。失策啊,bfs,dfs都试了的我,学长的思路更简单啊,删了就不想再写了
#include <iostream> #include <string> #include <cstring> #include <queue> using namespace std; struct node{ int x,y; bool friend operator <(node a,node b){ if(a.x<b.x) return 1; else if(a.x==b.x&&a.y<b.y) return 1; return 0; } }AC[400]; char s[20][20]; int vis[20][20]; int main(){ memset(s,\'B\',sizeof(s)); while(~scanf("%s",s[1]+1)){ memset(vis,1,sizeof(vis)); for(int i=2;i<20;i++) cin>>s[i]+1; int f=0; for(int i=1;i<20;i++){ for(int j=1;j<20;j++){ if(s[i][j]==\'W\'){ if(s[i+1][j]==\'.\'&&vis[i+1][j]){ AC[f].x=i+1; AC[f++].y=j; s[i+1][j]==\'B\'; vis[i+1][j]=0; } if(s[i-1][j]==\'.\'&&vis[i-1][j]){ AC[f].x=i-1; AC[f++].y=j; s[i-1][j]==\'B\'; vis[i-1][j]=0; } if(s[i][j+1]==\'.\'&&vis[i][j+1]){ AC[f].x=i; AC[f++].y=j+1; s[i][j+1]==\'B\'; vis[i][j+1]=0; } if(s[i][j-1]==\'.\'&&vis[i][j-1]){ AC[f].x=i; AC[f++].y=j-1; s[i][j-1]==\'B\'; vis[i][j-1]=0; }} }} if(!f){printf("YuYu Wins!\\n"); continue;} sort(AC,AC+f); for(int i=0;i<f;i++) printf("%d %d\\n",AC[i].x,AC[i].y); memset(s,\'B\',sizeof(s)); } return 0; }
5266: 三角形相似
总提交: 299 测试通过:72
描述
给定两个三角形的各条边边长,问这两个三角形是否相似。
输入
输入数据有多组,每组有两行,每行3个正整数,分别是两个三角形的三条边长(不超过100,数据保证满足三角形条件)。
输出
每组输出一个“Yes”或者“No”,分别表示相似或者不相似。
样例输入
3 4 5
6 8 10
样例输出
Yes
忘记转成浮点数的尴尬,错了两次吧,其实我那手速也不可能首A
三角形相似,对应边成比例,所以要把给定数值sort一下
#include <stdio.h> #include <math.h> #include <iostream> using namespace std; int main() { int a[3],b[3]; while(cin>>a[0]>>a[1]>>a[2]>>b[0]>>b[1]>>b[2]){ sort(a,a+3); sort(b,b+3); int f=0; double c=a[0]*1.0/b[0]; for(int i=1;i<3;i++){ if(fabs(a[i]*1.0/b[i]-c)<1e-6) continue; else{ puts("No"); f=1; break; } } if(f==0)puts("Yes");} return 0; }
5267: 卡片游戏
总提交: 129 测试通过:14
描述
爸爸正在和YuYu玩一个卡片游戏,共有N张卡片,每张卡片分别写上1, 2, 3, ..., N数字,现在爸爸报出一个数字X,要求YuYu从中找出一段连续数字的卡片,使其和等于X。
如果有多个答案,爸爸要求卡片的数目越多越好。
YuYu还是一个二年级小朋友,现在她希望能求助于你!
输入
输入数据有多组(不超过50组),每组占一行,每行两个整数N(1<=N<=10^8)和X(-10^9<=X<=10^9)。
输出
每组输出两个数,表示卡片对应连续数字的第一个和最后一个的数字值,每组占一行,空格隔开, 如果答案不存在输出“Error”。
样例输入
3 3
2 3
2 4
样例输出
1 2
1 2
Error
因式分解,自己手残,用来测试的却没有改过来,GG
假设第一张牌是e,最后一张牌是y。(e+y)*(y-e+1)/2=x;所以就枚举下(y-e+1),解方程就好了
#include <stdio.h> #include <math.h> int main(){ int n,x; while(~scanf("%d%d",&n,&x)){ if(x<0){ printf("Error\\n"); continue; } int f=1; x*=2; for(int i=sqrt(x);i;i--){ if(x%i==0){ int c=x/i; if((i+c)%2){ int y=(i+c-1)/2; int e=c-y; if(y<=n&&e>0) { printf("%d %d\\n",e,y); f=0;break;} } } } if(f)printf("Error\\n"); } return 0;}
5269: 玛祖游戏
总提交: 37 测试通过:12
描述
玛祖是一款非常经典的游戏,游戏的角色是一只青蛙,青蛙每次可以吐出一颗珠子,如果将珠子吐到场景中相同颜色的珠子旁边(称为击中),当三个或者三个以上的同颜色珠子在一起的时候便可以消掉,如果消掉后还有相同颜色的珠子,则可以继续消除(我们称为连击)。
YuYu也很喜欢这个游戏,而且希望连击次数越多越好,因此每次当她发现击中某种颜色的珠子能达到最大连击次数时,她总是等待该颜色出现!
现在给定已经出现在游戏场景中的珠子队列,问瑜瑜可能达到的最大连击次数是多少?
为了简化问题,我们的游戏规则是只要有两个颜色相同的珠子连在一起都可以消掉。
输入
输入数据有多组,每组占一行,每行一个由小写字母组成的字符串,长度不超过100000,表示游戏场景中的珠子队列,每个字母代表一种颜色。
输出
每组输出一个数字,表示最大的连击次数,该结果不会超过10000。
样例输入
b
aaabaaaa
ccccccccaaaaaaabbbdddddddeeeeeeeddddddbbbaaaaaaccccc
样例输出
1
2
5
这个祖玛是修改版的,两个就可以消除,所以先预处理得到单个字母的字符串。你打进去一个,如果是回文的话就一直连击啊。但是当时没想到,最后一小时我也不不知道我干了什么
现在我智商还是有问题的,一直少打了一个0,就是找最长回文串啊
#include <stdio.h> char s[100005]; int main() { char c; while((s[0]=getchar())!=EOF) { int f=0,ma=1; while((c=getchar())!=\'\\n\'){ if(c!=s[f]) s[++f]=c; } for(int i=1; i<f; i++) { int ans=1; int l=i-1,r=i+1; while(l>=0&&r<=f) { if(s[l]!=s[r]) break; l--; r++; ans++; } if(ans>ma)ma=ans; } printf("%d\\n",ma); } return 0; }
以上是关于2017年“达内杯”台州学院第十届大学生程序设计竞赛 非官方题解的主要内容,如果未能解决你的问题,请参考以下文章