本篇题解所使用的语言是C++,部分其他语言的选手可能需要理解做法后自行编写对应语言的代码。
本次比赛我认为值得一提的是7-1、7-6、7-7、7-10、和7-15,可以考虑重点看看这几道题的代码。
7-1 连续因子 一个正整数 N 的因子中可能存在若干连续的数字。例如 630 可以分解为 3×5×6×7,其中 5、6、7 就是 3 个连续的数字。给定任一正整数 N,要求编写程序求出最长连续因子的个数,并输出最小的连续因子序列。
输入格式 输入在一行中给出一个正整数 N(1 <N<2 31 )。
输出格式 首先在第 1 行输出最长连续因子的个数;然后在第 2 行中按 因子1*因子2*……*因子k 的格式输出最小的连续因子序列,其中因子按递增顺序输出,1 不算在内。
输入样例
输出样例
鸣谢用户 漏穿雪 补充数据!
题解 我们考虑从2开始枚举因子1,然后判断因子1开始的k在满足题目要求的连续时最长可以为多少,在出现更大的k时更新答案。 例如,针对630,我们从2开始枚举出了以下几种情况
2*3
3
5*6*7
6*7
7
9*10
10
14
15
18
21
考虑我们只需要枚举到√ N ,这是因为其余的部分k只能为1。 由于 13 ! = 6 , 227 , 020 , 800 > 2 31 ,故k最大不会超过11,又由于对于一个素数,我们判断的时间是O ( √ N ) ,所以整体的时间复杂度就是O ( 10 √ N ) 。
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 # include <bits/stdc++.h> using namespace std; int n,m; int ans= 0 ,an,sqn; int main () { cin>>n;sqn= sqrt (n); for ( int i= 2 ;i<=sqn;i++) { m=n; for ( int j=i;;j++) { if (m%j!= 0 ) { if (ans<j-i) { ans=j-i; an=i; } break ; } m/=j; } } if (!ans) ans= 1 ,an=n; printf ( "%d" ,ans); for ( int i= 0 ;i<ans;i++) { printf ( "%c%d" ,i== 0 ? '\n' : '*' ,i+an); } return 0 ; }
7-2 我也会加密 字符串加密可以理解为对字符串的一种固定方式的变形,现定义一种基于种子数字的加密方法,首先计算种子数字,计算方法为将该字符串的长度对5求余加1,以该数字为间隔,得到原字符串的子串并求逆得到最终的密码。
输入格式 原字符串
输出格式 加密后的字符串
输入样例 在这里给出一组输入。例如:
输出样例 在这里给出相应的输出。例如:
题解 按照题意模拟即可
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 # include <bits/stdc++.h> using namespace std; string s; char sta[ 100005 ]; int l; int main () { cin>>s; int n=s. length ()% 5 + 1 ; for ( int i= 0 ;i<s. length ();i+=n) { sta[l++]=s[i]; } for ( int i=l -1 ;i>= 0 ;i--) { printf ( "%c" ,sta[i]); } return 0 ; }
7-3 骑车还是走路? 在校园里,没有自行车,上课办事会很不方便。但实际上,并非去办任何事情都是骑车快。因为骑车总要找车、开锁、停车、锁车等,这要耽误一些时间。假设找到自行车,开锁并骑上自行车的时间为27秒;停车锁车的时间为23秒;步行每秒行走1.2米,骑车每秒行走3.0米。 编写程序判断走不同的距离去办事,是骑车快还是走路快。
输入格式 输入一个数,表示距离
输出格式 如果输入的距离骑车快,输出”Bike”;如果是走路快,输出”Walk”;如果一样快,输出”All”。
输入样例
输出样例
题解 按照题意模拟即可
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 # include <bits/stdc++.h> using namespace std; double bike,walk,m; int main () { cin>>m; bike= 27 + 23 +m/ 3.0 ; walk=m/ 1.2 ; if (bike<walk) printf ( "Bike" ); else if (bike>walk) printf ( "Walk" ); else printf ( "All" ); return 0 ; }
7-4 虫子吃苹果 你买了一箱n个苹果,很不幸的是买完时箱子里混进了一条虫子。虫子每x小时能吃掉一个苹果,假设虫子在吃完一个苹果之前不会吃另一个,那么经过y小时你还有多少个完整的苹果? 编写程序进行计算。
输入格式 在同一行输入n、x和y,以逗号隔开
输出格式 还剩下完整的苹果个数
输入样例 以下输入表示:一箱10个苹果,虫子每4个小时吃一个苹果,经过9小时
输出样例 以下输出表示:还剩下几个完整的苹果?
题解 按照题意模拟即可
代码 1 2 3 4 5 6 7 8 9 10 11 12 # include <bits/stdc++.h> using namespace std; int n,m,k; int main () { scanf ( "%d,%d,%d" ,&n,&m,&k); n-=(k+m -1 )/m; cout<<n; return 0 ; }
7-5 纵横 莫大侠练成纵横剑法,走上了杀怪路,每次仅出一招。这次,他遇到了一个正方形区域,由n×n个格子构成,每个格子(行号、列号都从1开始编号)中有若干个怪。莫大侠施展幻影步,抢占了一个格子,使出绝招“横扫四方”,就把他上、下、左、右四个直线方向区域内的怪都灭了(包括抢占点的怪)。请帮他算算他抢占哪个位置使出绝招“横扫四方”能杀掉最多的怪。如果有多个位置都能杀最多的怪,优先选择按行优先最靠前的位置。例如样例中位置(1,2)、(1,3),(3,2),(3,3)都能杀5个怪,则优先选择位置(1,2)。
输入格式 首先输入一个正整数T,表示测试数据的组数,然后是T组测试数据。对于每组测试,第一行输入n(3≤n≤20),第二行开始的n行输入n×n个格子中的怪数(非负整数)。
输出格式 对于每组测试数据输出一行,包含三个整数,分别表示莫大侠抢占点的行号和列号及所杀的最大怪数,数据之间留一个空格。
输入样例
输出样例
题解 循环暴力求解即可。这里可以采用行列记录的方法优化一维的复杂度。
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 # include <bits/stdc++.h> using namespace std; int T; int n,a[ 25 ][ 25 ],col[ 25 ],rol[ 25 ]; pair< int , int >anp; int ans= 0 ; int main () { cin>>T; while (T--> 0 ) { memset (a, 0 , sizeof (a)); memset (col, 0 , sizeof (col)); memset (rol, 0 , sizeof (rol)); ans= 0 ; scanf ( "%d" ,&n); for ( int i= 1 ;i<=n;i++) for ( int j= 1 ;j<=n;j++) scanf ( "%d" ,&a[i][j]); for ( int i= 1 ;i<=n;i++) { for ( int j= 1 ;j<=n;j++) { col[i]+=a[i][j]; rol[j]+=a[i][j]; } } for ( int i= 1 ;i<=n;i++) { for ( int j= 1 ;j<=n;j++) { int nw=col[i]+rol[j]-a[i][j]; if (nw>ans) { ans=nw; anp= make_pair (i,j); } } } printf ( "%d %d %d\n" ,anp.first,anp.second,ans); } return 0 ; }
7-6 小明打字 小明正使用Microsoft Word打一篇文档,文档只包含a-z的小写字母和空格,在打字过程中可能会一次或多次按下Home键、End键、←方向键、→方向键、Insert键、Backspace键。请编写程序,给定小明在键盘上按键的序列,输出小明屏幕上最终显示的文本。 提示:Home键会将当前光标移至文本开始位置,End键当前光标移至文本尾,←键和→键会使当前光标左移或右移一个位置(如果光标在文档头则无法左移,光标在文档尾则无法右移),Insert键会在插入和替换文本间切换(默认是插入状态),Backspace键会删除当前光标前的一个字符。
输入格式 输入为不超过50000个字符,表示小明的按键序列。包含a-z的小写字母、空格以及字符[、]、{、}、-、=。其中字符“[”表示Home键,“]”表示End键,“{”表示←键,“}”表示→键,“-”表示Insert键,“=”表示Backspace键。
输出格式 输出为在小明屏幕上最终显示的文本。最后一个字母后没有回车或换行。
输入样例1 1 jilin[i lofe {{-v- } ] universiti =y
输出样例1
输入样例2
输出样例2
输入样例3
输出样例3
输入样例4
输出样例4
题解 对于C++选手来说,此题是一道STL的模板题。 我们设定两个值,当前光标和是否插入状态,并将题目中给的几个操作进行转换:
[ 转换为 将光标移到开头
] 转换为 将光标移到结尾
{ 转换为 将光标左移一位,这里要注意如果光标已经在开头,就不要移动
} 转换为 将光标右移一位,这里要注意如果光标已经在结尾,就不要移动
- 转换为 切换插入和替换状态的标记值
= 转换为删除光标前一位字符,并将光标左移一位
其他字符
如果为插入状态,则在光标位置插入字符并将光标右移一位
如果为替换状态,则将光标位置的字符替换并将光标右移一位
我们可以利用string类的如下函数
erase(pos=0,len=npos)
insert(pos,n,c)
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 # include <bits/stdc++.h> using namespace std; string str,s; char c; int nw= 0 ,ist= 1 ; int main () { getline (cin,str); int l=str. length (); for ( int i= 0 ;i<l;i++) { c=str[i]; if (c== '-' )ist^= 1 ; else if (c== '[' )nw= 0 ; else if (c== ']' )nw=s. length (); else if (c== '{' )nw= max ( 0 ,nw -1 ); else if (c== '}' )nw= min (( int )s. length (),nw+ 1 ); else if (c== '=' ) s. erase (nw= max ( 0 ,nw -1 ), 1 ); else { if (ist) s. insert (nw, 1 ,c); else s[nw]=c; nw++; } } cout<<s; return 0 ; }
7-7 锯齿几何 锯齿是由严格的高低不同的刀片组成,而锯齿数组指的是数组中的相邻元素一高一低严格不同。一个元素和两个不同的元素是齿数较少的锯齿数组,因空集属于任何子集,我们规定,空数组也是锯齿数组。如{2,30,5,7}是锯齿数组,而{2,2,30,8,5,7}不是锯齿数组,但我们可以删除2和8,构成长度为4的新的锯齿数组。编写程序,对输入的整数数组,计算删除若干元素后,构成的最长的锯齿数组(可删除元素,但其它元素的相对位置保持不变)的长度。
输入样例1 第一行,数组长度N,第二行是空格分隔的N个整数。
1 2 9 18 45 30 50 10 17 8 25 19
输出样例1 输出构成的最长的锯齿数组(本例中数据就是锯齿数组,故长度就是9)。
输入样例2 1 2 13 18 19 20 45 30 50 10 17 10 9 8 25 19
输出样例2 输出构成的最长的锯齿数组(本例中数据,至少可删除成上例中的锯齿数组,故长度最大长度也是9)。
输入样例3
输出样例3 输出构成的最长的锯齿数组(最多只能够留下两个齿)。
题解 一道双状态dp题。 我们对于每个点,都设计两个状态,这个点到下一个点是变高up和这个点到下一个点是变低dw两个状态,状态的值表示从这个点开始往后符合要求的最长长度。 初始状态每个点的两个状态都是1,因为每个点都可以仅剩下自己。 转移的方法是从后向前转移,后面点的dw状态可以转移给前面点的up状态当且仅当后面的点的高度大于前面的点;后面点的up状态可以转移给前面点的dw状态当且仅当后面的点的高度小于前面的点。 方程为u p i = m a x ( u p i , d w j + 1 ) , i < j , a i < a j d w i = m a x ( d w i , u p j + 1 ) , i < j , a i > a j 最终状态是m a x ( m a x ( u p i , d w i ) )
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 # include <bits/stdc++.h> using namespace std; int n; int a[ 1005 ],up[ 1005 ],dw[ 1005 ]; int ans= 0 ; int main () { scanf ( "%d" ,&n); for ( int i= 1 ;i<=n;i++) scanf ( "%d" ,&a[i]); for ( int i=n;i>= 1 ;i--) { up[i]=dw[i]= 1 ; for ( int j=i+ 1 ;j<=n;j++) { if (a[j]>a[i]) up[i]= max (up[i],dw[j]+ 1 ); else if (a[j]<a[i]) dw[i]= max (dw[i],up[j]+ 1 ); } ans= max (ans, max (up[i],dw[i])); } printf ( "%d" ,ans); return 0 ; }
7-8 秋天的第一杯奶茶 2020年入秋后,朋友圈和微博上疯狂转发着自己收到的“秋天的第一杯奶茶”。然而小明却什么也没有收到,但是学校举行了这样一场活动:通过5道编写程序题目中的3道即可获得一杯奶茶。小明也想喝到秋天的第一杯奶茶。下面就请你判断小明是否有机会拿到学校的奶茶。
输入格式 两行,第一行给出一个整数N(1<=N<=100),随后N行,每行给出一个长度为5的字符串(仅包含Y和N,分别代表5个题目小明是否通过),Y代表本题通过,N代表本题未通过。
输出格式 可以拿到奶茶输出“YES”,否则输出“NO”(输出不含双引号)。
输入样例
输出样例
题解 按照题意模拟即可
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 # include <bits/stdc++.h> using namespace std; int n,ny,nn; char c; int main () { cin>>n; for ( int i= 1 ;i<=n;i++) { ny= 0 ,nn= 0 ; scanf ( "\n" ); for ( int j= 1 ;j<= 5 ;j++) { scanf ( "%c" ,&c); if (c== 'Y' ) ny++; if (c== 'N' ) nn++; } if (ny>nn) printf ( "YES\n" ); else printf ( "NO\n" ); } return 0 ; }
7-9 镇长修路 某地对偏远地区实行“村村通”工程,目标是使整个地区任何两个村落间都可以实现快速交通(但不一定有直接的快速道路相连,只要互相间接通过快速路可达即可)。现得到拟修建道路的费用,现请你编写程序,计算出全地区畅通需要的最低成本。
输入格式 输入的第一行给出村庄数目N (1≤N≤20)和拟修建的道路数M
接下来的M行对应修建每条村庄间道路的成本,每行给出3个正整数,分别是两个村庄的编号(从1编号到N),此两村庄间道路的成本。
输出格式 输出需修建的道路,每行输出一条道路,形式如:道路1编号,道路2编号,费用。(编号小的放前面,编号大的放后面,逗号为英文状态下的逗号)
修建时优先修建最短的路,如果有多条路最短,则优先修建道路1编号小的路,再如果两条路道路1编号相同,则优先输出道路2小的路
输入样例 在这里给出一组输入。例如:
1 2 3 4 5 6 7 4 6 1 2 1 1 3 4 1 4 1 2 3 3 2 4 2 3 4 5
输出样例 在这里给出相应的输出。例如:
题解 最小生成树模板题
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 # include <bits/stdc++.h> using namespace std; int n,m; int fa[ 25 ]; int getfa ( int x) { return fa[x]==x?x:fa[x]= getfa (fa[x]);} void merge ( int x, int y) { int fx= getfa (x),fy= getfa (y); if (fx==fy) return ; fa[fx]=fy; } struct edge { int u,v,w; }e[ 10005 ]; bool cmp (edge a,edge b) { if (a.w!=b.w) return a.w<b.w; if (a.u!=b.u) return a.u<b.u; return a.v<b.v; } int main () { scanf ( "%d%d" ,&n,&m); for ( int i= 1 ;i<=n;i++)fa[i]=i; for ( int i= 1 ;i<=m;i++) { scanf ( "%d%d%d" ,&e[i].u,&e[i].v,&e[i].w); if (e[i].u>e[i].v) swap (e[i].u,e[i].v); } sort (e+ 1 ,e+m+ 1 ,cmp); int added= 0 ; for ( int i= 1 ;i<=m&&added<n -1 ;i++) { int fu= getfa (e[i].u),fv= getfa (e[i].v); if (fu==fv) continue ; merge (fu,fv); added++; printf ( "%d,%d,%d\n" ,e[i].u,e[i].v,e[i].w); } return 0 ; }
7-10 装修 胡老师买了新房,正在搞装修,装修公司太坑了,于是胡老师就自己找装修师傅来干活,但是装修的很多环节是环环相扣的,比如,要先刷墙才能铺木地板,有些环节呢,又是互相不干扰的,比如厨房的装修和窗帘的安装。但是每个装修师傅的时间又受他接的单所限制。所以必须仔细安排才能把房子装修好。胡老师收到了若干种不同装修师傅的安排,他想尽快装修好了入住,你能帮他吗?
输入格式 第一行输入正整数T(T< 20),表示有T个方案,对于每一个方案,第一行输入两个正整数N(< 100)和M,其中N是装修时间点的个数,从0开始编号,M是装修环节的个数。随后M行,每行输入三个非负整数表示一个装修环节,Start End Delay,Start表示开始时间点编号,End表示结束时间点编号,Delay表示装修需要时间。
输出格式 对每一个方案,如果方案可行,则在一行里输入最早结束的时间,如果不可行,则输出Impossible!。
输入样例 在这里给出一组输入。例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 2 7 10 0 1 3 0 2 2 0 3 6 1 3 2 2 3 1 1 4 4 3 4 1 2 5 3 4 6 3 5 6 4 3 3 0 1 1 1 2 2 2 0 3
输出样例 在这里给出相应的输出。例如:
题解 拓扑题,记录每个点的入度,从无入度的点开始访问,访问到一条边减少到点的入度,每个点开始访问的时间为最后一条前边遍历完成的时间,答案为最后一个被遍历到的点的访问时间。
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 # include <bits/stdc++.h> using namespace std; int T; int n,m,cnt,ans; int inc[ 105 ],head[ 105 ]; struct edge { int ne,to,w; }e[ 200005 ]; queue< int >q; bool vis[ 105 ]; int st[ 105 ]; void clea () { cnt= 0 ,ans= 0 ; memset (inc, 0 , sizeof (inc)); memset (head, 0 , sizeof (head)); memset (e, 0 , sizeof (e)); memset (st, 0 , sizeof (st)); memset (vis, 0 , sizeof (vis)); while (!q. empty ())q. pop (); } void add ( int u, int v, int w) { e[++cnt]=(edge){head[u],v,w};head[u]=cnt; } int main () { cin>>T; while (T--> 0 ) { clea (); scanf ( "%d%d" ,&n,&m); for ( int i= 1 ,u,v,w;i<=m;i++) { scanf ( "%d%d%d" ,&u,&v,&w);u++;v++; inc[v]++; add (u,v,w); } for ( int i= 1 ;i<=n;i++) { if (!inc[i]) { q. push (i); } } while (!q. empty ()) { int x=q. front ();q. pop (); vis[x]= 1 ; for ( int i=head[x];i;i=e[i].ne) { int y=e[i].to; inc[y]--; st[y]= max (st[y],st[x]+e[i].w); } for ( int i= 1 ;i<=n;i++) { if (!vis[i]&&!inc[i]) q. push (i); } } for ( int i= 1 ;i<=n;i++) { ans= max (ans,st[i]); if (!vis[i]) { printf ( "Impossible!\n" ); goto nextloop; } } printf ( "%d\n" ,ans); nextloop: 0 ; } return 0 ; }
7-11 人与神 跨界大神 L. Peter Deutsch 有一句名言:“To iterate is human, to recurse divine.”(迭代的是人,递归的是神)。本题就请你直接在屏幕上输出这句话。
输入格式 本题没有输入。
输出格式 在一行中输出 To iterate is human, to recurse divine.。
输入样例 无
输出样例 1 To iterate is human, to recurse divine.
题解 签到题
代码 1 2 3 4 5 6 7 8 9 10 11 # include <bits/stdc++.h> using namespace std; int main () { cout<< "To iterate is human, to recurse divine." ; return 0 ; }
7-12 强迫症 小强在统计一个小区里居民的出生年月,但是发现大家填写的生日格式不统一,例如有的人写 199808,有的人只写 9808。有强迫症的小强请你写个程序,把所有人的出生年月都整理成 年年年年-月月 格式。对于那些只写了年份后两位的信息,我们默认小于 22 都是 20 开头的,其他都是 19 开头的。
输入格式 输入在一行中给出一个出生年月,为一个 6 位或者 4 位数,题目保证是 1000 年 1 月到 2021 年 12 月之间的合法年月。
输出格式 在一行中按标准格式 年年年年-月月 将输入的信息整理输出。
输入样例 1
输出样例 1
输入样例 2
输出样例 2
输入样例 3
输出样例 3
题解 按照题意模拟即可
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 # include <bits/stdc++.h> using namespace std; int y,m; char s[ 10 ]; int main () { scanf ( "%s" ,s); if ( strlen (s)== 4 ) { sscanf (s, "%2d%d" ,&y,&m); if (y< 22 )y+= 2000 ; else y+= 1900 ; } else sscanf (s, "%4d%d" ,&y,&m); printf ( "%04d-%02d" ,y,m); return 0 ; }
7-13 病毒溯源 病毒容易发生变异。某种病毒可以通过突变产生若干变异的毒株,而这些变异的病毒又可能被诱发突变产生第二代变异,如此继续不断变化。
现给定一些病毒之间的变异关系,要求你找出其中最长的一条变异链。
在此假设给出的变异都是由突变引起的,不考虑复杂的基因重组变异问题 —— 即每一种病毒都是由唯一的一种病毒突变而来,并且不存在循环变异的情况。
输入格式 输入在第一行中给 出一个正整数 N(≤10 4 ),即病毒种类的总数。于是我们将所有病毒从 0 到 N−1 进行编号。
随后 N 行,每行按以下格式描述一种病毒的变异情况:
其中 k 是该病毒产生的变异毒株的种类数,后面跟着每种变异株的编号。第 i 行对应编号为 i 的病毒(0≤i<N)。题目保证病毒源头有且仅有一个。
输出格式 首先输出从源头开始最长变异链的长度。
在第二行中输出从源头开始最长的一条变异链,编号间以 1 个空格分隔,行首尾不得有多余空格。如果最长链不唯一,则输出最小序列。
注:我们称序列 a 1 , ⋯ , a n 比序列b 1 , ⋯ , b n “小”,如果存在 1 ≤ k ≤ n 满足 a i = b i 对所有 i < k 成立,且 a k < b k 。
输入样例 1 2 3 4 5 6 7 8 9 10 11 10 3 6 4 8 0 0 0 2 5 9 0 1 7 1 2 0 2 3 1
输出样例
题解 本题是一道搜索题,写搜索记录最长链即可。
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 # include <bits/stdc++.h> using namespace std; int n; int head[ 10005 ],cnt,inc[ 10005 ]; struct edge { int ne,to; }e[ 10005 ]; void add ( int u, int v) { e[++cnt]=(edge){head[u],v};head[u]=cnt; } int ans,an[ 10005 ]; int nw[ 10005 ]; void dfs ( int x, int d) { if (!head[x]) { if (d>ans) { ans=d; for ( int i= 1 ;i<=d;i++) { an[i]=nw[i]; } } else if (d==ans) { bool flg= 0 ; for ( int i= 1 ;i<=d;i++) { if (nw[i]<an[i]) flg= 1 ; else if (nw[i]>an[i]) break ; } if (flg) { for ( int i= 1 ;i<=d;i++) an[i]=nw[i]; } } return ; } for ( int i=head[x];i;i=e[i].ne) { nw[d+ 1 ]=e[i].to; dfs (e[i].to,d+ 1 ); nw[d+ 1 ]= 0 ; } } int main () { scanf ( "%d" ,&n); for ( int i= 1 ,k,l;i<=n;i++) { scanf ( "%d" ,&k); for ( int j= 1 ;j<=k;j++) { scanf ( "%d" ,&l); add (i,l+ 1 ); inc[l+ 1 ]++; } } for ( int i= 1 ;i<=n;i++) { if (!inc[i]) { nw[ 1 ]=i; dfs (i, 1 ); nw[ 1 ]= 0 ; } } printf ( "%d" ,ans); for ( int i= 1 ;i<=ans;i++) { printf ( "%c%d" ,i== 1 ? '\n' : ' ' ,an[i] -1 ); } return 0 ; }
7-14 大大的叉 打印出n阶的“叉”,这个叉图案由字符‘+’和‘X’构成,n越大,这个图案也就越大
输入格式 一个正整数n,1<=n<=20
输出格式 一个n阶叉图案
输入样例1
输出样例1
输入样例2
输出样例2 1 2 3 4 5 6 7 8 9 X +++X +X +X + ++X ++ +X +X + X +++X
输入样例3 在这里给出一组输入。例如:
输出样例3 在这里给出相应的输出。例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 +++++++++++ + +++++++++ + ++ +++++++ ++ +++ +++++ +++ ++++ +++ ++++ +++++ + +++++ ++++++ ++++++ +++++ + +++++ ++++ +++ ++++ +++ +++++ +++ ++ +++++++ ++ + +++++++++ + +++++++++++
题解 按照题意模拟即可
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 # include <bits/stdc++.h> using namespace std; int n; int main () { cin>>n; for ( int i= 1 ;i<= 2 *n -1 ;i++) { for ( int j= 1 ;j<= 2 *n -1 ;j++) { if (i==j||i+j== 2 *n) printf ( "X" ); else printf ( "+" ); } printf ( "\n" ); } return 0 ; }
7-15 3824经典游戏 24点游戏,也叫3824游戏,是一款经典的心算数字游戏。给出区间[1,13]内的四个整数,验证能否用加、减、乘、除四则运算,将这四个整数组合成24。比如:(3,8,2,4) 可以算出 8*(4−3+2)=24或者(8−4)*(2*3)=24,而(1,1,2,2)无法算出24。注意整除必须除尽,即9/2+10+10=24这种计算无效。
输入格式 第一行给出正整数N(1≤N≤1000)。接下来N行数据,每行给出四个正整数a i b i c i d i ,用空格分开。(∀ i ∈ 1 , … , N : 1 ≤ a i b i c i d i ≤ 13 )
输出格式 输出N行数据,第i行对应输入数据(a i b i c i d i ),如果能算出24,则输出24,如果不能则输出0。
输入样例 1 2 3 4 5 4 1 1 1 1 1 2 3 4 3 9 11 2 13 3 5 7
输出样例
(1,1,1,1)和(3,9,11,2)都无法算出24,(1,2,3,4)和(13,3,5,7)可以算出:1*2*3*4=24和(13*5+7)/3=24。
题解 整理下求24点的思路,给定四个数字,不限定他们的排序,自己指定三个运算符和括号添加位置,让结果等于24。 于是我们将四个数读入后排序,并使用next_permutation函数得到这四个数的全排列。 接着我们枚举三个运算符,一共有4 3 种情况。 然后我们指定括号,这里指定括号可以理解为指定运算符的运算顺序,也就是123,132,213,231,312,321这几种,其中132和312这两种是相同的结果,于是就只有五种运算顺序。 枚举完所有情况后我们计算结果并判断是否为24即可。 需要注意的是对于除法,由于必须整除,我们最好写浮点运算,同时排除下除数是0的情况即可。
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 # include <bits/stdc++.h> using namespace std; int T; int a[ 5 ]; int ans= 0 ; char op[]= "/*-+" ; bool d ( int x) { if (x== 24 ) { ans= 24 ; return 1 ; } return 0 ; } int cal ( int x, int y, int tp) { if (tp== 0 ) return x/y; if (tp== 1 ) return x*y; if (tp== 2 ) return x-y; if (tp== 3 ) return x+y; } bool model1 ( int t1, int t2, int t3) { int nw=a[ 1 ]; if (!t1&&(!a[ 2 ]||nw%a[ 2 ]!= 0 )) return false ; nw= cal (nw,a[ 2 ],t1); if (!t2&&(!a[ 3 ]||nw%a[ 3 ]!= 0 )) return false ; nw= cal (nw,a[ 3 ],t2); if (!t3&&(!a[ 4 ]||nw%a[ 4 ]!= 0 )) return false ; nw= cal (nw,a[ 4 ],t3); return d (nw); } bool model2 ( int t1, int t2, int t3) { int nw,nw1=a[ 1 ],nw2=a[ 3 ]; if (!t1&&(!a[ 2 ]||nw1%a[ 2 ]!= 0 )) return false ; nw1= cal (nw1,a[ 2 ],t1); if (!t3&&(!a[ 4 ]||nw2%a[ 4 ]!= 0 )) return false ; nw2= cal (nw2,a[ 4 ],t3); if (!t2&&(!nw2||nw1%nw2!= 0 )) return false ; nw= cal (nw1,nw2,t2); return d (nw); } bool model3 ( int t1, int t2, int t3) { int nw=a[ 2 ]; if (!t2&&(!a[ 3 ]||nw%a[ 3 ]!= 0 )) return false ; nw= cal (nw,a[ 3 ],t2); if (!t1&&(!nw||a[ 1 ]%nw!= 0 )) return false ; nw= cal (a[ 1 ],nw,t1); if (!t3&&(!a[ 4 ]||nw%a[ 4 ]!= 0 )) return false ; nw= cal (nw,a[ 4 ],t3); return d (nw); } bool model4 ( int t1, int t2, int t3) { int nw=a[ 2 ]; if (!t2&&(!a[ 3 ]||nw%a[ 3 ]!= 0 )) return false ; nw= cal (nw,a[ 3 ],t2); if (!t3&&(!a[ 4 ]||nw%a[ 4 ]!= 0 )) return false ; nw= cal (nw,a[ 4 ],t3); if (!t1&&(!nw||a[ 1 ]%nw!= 0 )) return false ; nw= cal (a[ 1 ],nw,t1); return d (nw); } bool model5 ( int t1, int t2, int t3) { int nw=a[ 3 ]; if (!t3&&(!a[ 4 ]||nw%a[ 4 ]!= 0 )) return false ; nw= cal (nw,a[ 4 ],t3); if (!t2&&(!nw||a[ 2 ]%nw!= 0 )) return false ; nw= cal (a[ 2 ],nw,t2); if (!t1&&(!nw||a[ 1 ]%nw!= 0 )) return false ; nw= cal (a[ 1 ],nw,t1); return d (nw); } int main () { cin>>T; while (T--> 0 ) { ans= 0 ; for ( int i= 1 ;i<= 4 ;i++) scanf ( "%d" ,&a[i]); sort (a+ 1 ,a+ 5 ); do { for ( int i= 0 ;i< 4 ;i++) { for ( int j= 0 ;j< 4 ;j++) { for ( int k= 0 ;k< 4 ;k++) { if ( model1 (i,j,k)) goto nextloop; if ( model2 (i,j,k)) goto nextloop; if ( model3 (i,j,k)) goto nextloop; if ( model4 (i,j,k)) goto nextloop; if ( model5 (i,j,k)) goto nextloop; } } } } while ( next_permutation (a+ 1 ,a+ 5 )); nextloop: printf ( "%d\n" ,ans); } return 0 ; }
预览: