BASIC-21 VIP试题 Sine之舞
问题描述
最近FJ为他的奶牛们开设了数学分析课,FJ知道若要学好这门课,必须有一个好的三角函数基本功。所以他准备和奶牛们做一个“Sine之舞”的游戏,寓教于乐,提高奶牛们的计算能力。
不妨设
An=sin(1–sin(2+sin(3–sin(4+…sin(n))…)
Sn=(…(A1+n)A2+n-1)A3+…+2)An+1
FJ想让奶牛们计算Sn的值,请你帮助FJ打印出Sn的完整表达式,以方便奶牛们做题。
输入格式
仅有一个数:N<201。
输出格式
请输出相应的表达式Sn,以一个换行符结束。输出中不得含有多余的空格或换行、回车符。
样例输入
3
样例输出
((sin(1)+3)sin(1–sin(2))+2)sin(1–sin(2+sin(3)))+1
#include<iostream> using namespace std; int main() { void PrintAn(int); void PrintSn(int); int n; cin>>n; PrintSn(n); return 0; } void PrintAn(int n) { for(int i=1;i<=n;i++) { cout<<"sin("<<i; if(i!=n) { if(i%2!=0) cout<<"-"; else cout<<"+"; } else { for(int j=1;j<=n;j++) cout<<")"; } } } void PrintSn(int n) { for(int i=1;i<n;i++) cout<<"("; for(int i=1;i<=n;i++) { if(i!=n) { PrintAn(i); cout<<"+"<<n-i+1<<")"; } else { PrintAn(i); cout<<"+"<<n-i+1<<endl; } } }
BASIC-22 VIP试题 FJ的字符串
问题描述
FJ在沙盘上写了这样一些字符串:
A1 = “A”
A2 = “ABA”
A3 = “ABACABA”
A4 = “ABACABADABACABA”
… …
你能找出其中的规律并写所有的数列AN吗?
输入格式
仅有一个数:N ≤ 26。
输出格式
请输出相应的字符串AN,以一个换行符结束。输出中不得含有多余的空格或换行、回车符。
样例输入
3
样例输出
ABACABA
#include <bits/stdc++.h> using namespace std; void fun(int n) { if(n==1) cout << 'A'; else { fun(n-1); cout << (char)('A'+n-1);//printf("%c",a[n-1]); fun(n-1); } } int main () { int n; cin >> n; fun(n); return 0; }
BASIC-23 VIP试题 芯片测试
问题描述
有n(2≤n≤20)块芯片,有好有坏,已知好芯片比坏芯片多。
每个芯片都能用来测试其他芯片。用好芯片测试其他芯片时,能正确给出被测试芯片是好还是坏。而用坏芯片测试其他芯片时,会随机给出好或是坏的测试结果(即此结果与被测试芯片实际的好坏无关)。
给出所有芯片的测试结果,问哪些芯片是好芯片。
输入格式
输入数据第一行为一个整数n,表示芯片个数。
第二行到第n+1行为n*n的一张表,每行n个数据。表中的每个数据为0或1,在这n行中的第i行第j列(1≤i, j≤n)的数据表示用第i块芯片测试第j块芯片时得到的测试结果,1表示好,0表示坏,i=j时一律为1(并不表示该芯片对本身的测试结果。芯片不能对本身进行测试)。
输出格式
按从小到大的顺序输出所有好芯片的编号
样例输入
3
1 0 1
0 1 0
1 0 1
样例输出
1 3
#include <stdio.h> int n; int a[20][20]; int num[20]={0}; int main () { int i,j; scanf("%d",&n); for(i=1;i<=n;i++) for(j=1;j<=n;j++) { scanf("%d",&a[i][j]); if(a[i][j]==1) { num[j]++; //记录每一列的1 的个数 ,用于判断是否大于n/2 } } int flag=0;//设置输出格式 for(i=1;i<=n;i++) { if(num[i]>n/2) { if(flag==0) { printf("%d",i); flag=1; } else printf(" %d",i); } } return 0; }
BASIC-24 VIP试题 龟兔赛跑预测
问题描述
话说这个世界上有各种各样的兔子和乌龟,但是研究发现,所有的兔子和乌龟都有一个共同的特点——喜欢赛跑。于是世界上各个角落都不断在发生着乌龟和兔子的比赛,小华对此很感兴趣,于是决定研究不同兔子和乌龟的赛跑。他发现,兔子虽然跑比乌龟快,但它们有众所周知的毛病——骄傲且懒惰,于是在与乌龟的比赛中,一旦任一秒结束后兔子发现自己领先t米或以上,它们就会停下来休息s秒。对于不同的兔子,t,s的数值是不同的,但是所有的乌龟却是一致——它们不到终点决不停止。
然而有些比赛相当漫长,全程观看会耗费大量时间,而小华发现只要在每场比赛开始后记录下兔子和乌龟的数据——兔子的速度v1(表示每秒兔子能跑v1米),乌龟的速度v2,以及兔子对应的t,s值,以及赛道的长度l——就能预测出比赛的结果。但是小华很懒,不想通过手工计算推测出比赛的结果,于是他找到了你——清华大学计算机系的高才生——请求帮助,请你写一个程序,对于输入的一场比赛的数据v1,v2,t,s,l,预测该场比赛的结果。
输入格式
输入只有一行,包含用空格隔开的五个正整数v1,v2,t,s,l,其中(v1,v2<=100;t<=300;s<=10;l<=10000且为v1,v2的公倍数)
输出格式
输出包含两行,第一行输出比赛结果——一个大写字母“T”或“R”或“D”,分别表示乌龟获胜,兔子获胜,或者两者同时到达终点。
第二行输出一个正整数,表示获胜者(或者双方同时)到达终点所耗费的时间(秒数)。
样例输入
10 5 5 2 20
样例输出
D
4
样例输入
10 5 5 1 20
样例输出
R
3
样例输入
10 5 5 3 20
样例输出
T
4
注意题目的意思说赛跑是以整数秒为单位的,不存在0.5秒之类的情况,所以只需要考虑下一秒兔子和乌龟该怎么行动就行了。
#include <cstdio> int main () { int v1,v2,t,s,l,i=0; int ans1=0,ans2=0; scanf("%d %d %d %d %d",&v1,&v2,&t,&s,&l); while(ans1<l && ans2<l) { ans1+=v1; ans2+=v2; i++; if(ans1==l || ans2==l ) break; if(ans1-ans2>=t) ans1-=s*v1; } if(ans1>ans2) printf("R\n"); else if(ans1<ans2) printf("T\n"); else printf("D\n"); printf("%d",i); return 0; }
BASIC-25 VIP试题 回形取数
问题描述
回形取数就是沿矩阵的边取数,若当前方向上无数可取或已经取过,则左转90度。一开始位于矩阵左上角,方向向下。
输入格式
输入第一行是两个不超过200的正整数m, n,表示矩阵的行和列。接下来m行每行n个整数,表示这个矩阵。
输出格式
输出只有一行,共mn个数,为输入矩阵回形取数得到的结果。数之间用一个空格分隔,行末不要有多余的空格。
样例输入
3 3
1 2 3
4 5 6
7 8 9
样例输出
1 4 7 8 9 6 3 2 5
样例输入
3 2
1 2
3 4
5 6
样例输出
1 3 5 6 4 2
这道题关键在于判断何时转弯,采取dfs有点大才小用,用当前点四周还没有走过的点的个数来判断,会简单一点。详情看代码注释。
#include <bits/stdc++.h> using namespace std; int book[200][200];//book数组表示标记,标记为一代表已经走过 int a[200][200]; int main () { int m,n; int x=0,y=0,k=0,t=0; cin >> m >> n; int v[4][2]= {1,0,0,1,-1,0,0,-1}; //表示下一步方向的数组 for(int l=0;l<m;l++) for(int b=0;b<n;b++) cin >> a[l][b];//输入数据 while(1) { t=0; for(int j=0; j<4; j++) { //判断是否x,y点处四周是否走过,用t表示四周走过的点数。 if(book[x+v[j][0]][y+v[j][1]]==1||x+v[j][0]>=m||x+v[j][0]<0||y+v[j][1]>=n||y+v[j][1]<0) t++; } if(t==4)//如果四周都已走过证明这是最后一个点。 { cout << a[x][y] << endl; break; } cout << a[x][y] << ' '; book[x][y] = 1;//标记该点已经走过 //判断(x,y)是否在方形的四个角处,如果在就转弯。 if(book[x+v[k][0]][y+v[k][1]]==1||x+v[k][0]==m||x+v[k][0]<0||y+v[k][1]==n||y+v[k][1]<0) { k++; k%=4; } x += v[k][0];//改变x,y 继续判断下一个点 y += v[k][1]; } return 0; }
BASIC-26 VIP试题 报时助手
问题描述
给定当前的时间,请用英文的读法将它读出来。
时间用时h和分m表示,在英文的读法中,读一个时间的方法是:
如果m为0,则将时读出来,然后加上“o’clock”,如3:00读作“three o’clock”。
如果m不为0,则将时读出来,然后将分读出来,如5:30读作“five thirty”。
时和分的读法使用的是英文数字的读法,其中0~20读作:
0:zero, 1: one, 2:two, 3:three, 4:four, 5:five, 6:six, 7:seven, 8:eight, 9:nine, 10:ten, 11:eleven, 12:twelve, 13:thirteen, 14:fourteen, 15:fifteen, 16:sixteen, 17:seventeen, 18:eighteen, 19:nineteen, 20:twenty。
30读作thirty,40读作forty,50读作fifty。
对于大于20小于60的数字,首先读整十的数,然后再加上个位数。如31首先读30再加1的读法,读作“thirty one”。
按上面的规则21:54读作“twenty one fifty four”,9:07读作“nine seven”,0:15读作“zero fifteen”。
输入格式
输入包含两个非负整数h和m,表示时间的时和分。非零的数字前没有前导0。h小于24,m小于60。
输出格式
输出时间时刻的英文。
样例输入
0 15
样例输出
zero fifteen
这题主要是判断很多,需要细心
#include <cstdio> int main () { int h,m,r; char a[25][15]={"zero","one","two","three","four","five","six","seven","eight","nine","ten","eleven", "twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen", "twenty","twenty one","twenty two","twenty three","twenty four"}; scanf("%d %d",&h,&m); if(m==0) { printf("%s o'clock",a[h]); } else if(m>0 && m<=20) { printf("%s %s",a[h],a[m]); } else if(m>20 && m<=30) { r=m-20; printf("%s twenty %s",a[h],a[r]); } else if(m>30 && m<=40) { r=m-30; printf("%s thirty %s",a[h],a[r]); } else if(m>40 && m<=50) { r=m-40; printf("%s forty %s",a[h],a[r]); } else { r=m-50; printf("%s fifty %s",a[h],a[r]); } return 0; }
BASIC-27 VIP试题 2n皇后问题
问题描述
给定一个n*n的棋盘,棋盘中有一些位置不能放皇后。现在要向棋盘中放入n个黑皇后和n个白皇后,使任意的两个黑皇后都不在同一行、同一列或同一条对角线上,任意的两个白皇后都不在同一行、同一列或同一条对角线上。问总共有多少种放法?n小于等于8。
输入格式
输入的第一行为一个整数n,表示棋盘的大小。
接下来n行,每行n个0或1的整数,如果一个整数为1,表示对应的位置可以放皇后,如果一个整数为0,表示对应的位置不可以放皇后。
输出格式
输出一个整数,表示总共有多少种放法。
样例输入
4
1 1 1 1
1 1 1 1
1 1 1 1
1 1 1 1
样例输出
2
样例输入
4
1 0 1 1
1 1 1 1
1 1 1 1
1 1 1 1
样例输出
0
这题用到了深度优先算法dfs,问题的关键在于判断当前应该做什么。不太明白的可以看看这篇博客。
链接
#include <bits/stdc++.h> int tot, c[10], n, num; int map[10][10]; int vis[100][10]; void Dfs(int cur)//深度优先搜索 { if(cur == n) { for(int f = 0; f < n; f++) vis[tot][f] = c[f]; tot++; } else { for(int i = 0; i < n; i++) { if(map[cur][i] == 1) { int ok = 1; c[cur] = i; for(int j = 0; j < cur; j++) { if(c[cur] == c[j] || cur - c[cur] == j - c[j] || cur + c[cur] == j + c[j]) { ok = 0; break; } } if(ok) Dfs(cur + 1); } } } } bool isMutexLine(int a[], int b[]) //判断两行是否互斥 { for(int i = 0; i < n; i++) { if(a[i] == b[i]) //黑白皇后在同一格 return true; } return false; } void Search(int x) { for(int q = 0; q < x; q++) { for(int w = q + 1; w < x; w++) if(!isMutexLine(vis[q], vis[w])) num++; } printf("%d", 2 * num); } int main() { int i, j; scanf("%d", &n); for(i = 0; i < n; i++) for(j = 0; j < n; j++) scanf("%d", &map[i][j]); memset(c, -1, sizeof(c)); memset(vis, -1, sizeof(vis)); tot = 0; num = 0; Dfs(0); Search(tot); return 0; }
BASIC-28 VIP试题 Huffuman树
问题描述
Huffman树在编码中有着广泛的应用。在这里,我们只关心Huffman树的构造过程。
给出一列数{pi}={p0, p1, …, pn-1},用这列数构造Huffman树的过程如下:
1. 找到{pi}中最小的两个数,设为pa和pb,将pa和pb从{pi}中删除掉,然后将它们的和加入到{pi}中。这个过程的费用记为pa + pb。
2. 重复步骤1,直到{pi}中只剩下一个数。
在上面的操作过程中,把所有的费用相加,就得到了构造Huffman树的总费用。
本题任务:对于给定的一个数列,现在请你求出用该数列构造Huffman树的总费用。
例如,对于数列{pi}={5, 3, 8, 2, 9},Huffman树的构造过程如下:
1. 找到{5, 3, 8, 2, 9}中最小的两个数,分别是2和3,从{pi}中删除它们并将和5加入,得到{5, 8, 9, 5},费用为5。
2. 找到{5, 8, 9, 5}中最小的两个数,分别是5和5,从{pi}中删除它们并将和10加入,得到{8, 9, 10},费用为10。
3. 找到{8, 9, 10}中最小的两个数,分别是8和9,从{pi}中删除它们并将和17加入,得到{10, 17},费用为17。
4. 找到{10, 17}中最小的两个数,分别是10和17,从{pi}中删除它们并将和27加入,得到{27},费用为27。
5. 现在,数列中只剩下一个数27,构造过程结束,总费用为5+10+17+27=59。
输入格式
输入的第一行包含一个正整数n(n<=100)。
接下来是n个正整数,表示p0, p1, …, pn-1,每个数不超过1000。
输出格式
输出用这些数构造Huffman树的总费用。
样例输入
5
5 3 8 2 9
样例输出
59
哈夫曼树是数据结构中的一种寻找最小和路径的算法,很多大佬讲的很详细。这里给出csdn链接
#include <iostream> #include <algorithm> using namespace std; int main () { int a[100]; int i,n; scanf("%d",&n); for(i=0;i<n;i++) { scanf("%d",&a[i]); } sort(a,a+n); int sum=0; while(n>1) { i=0; a[i]=a[i]+a[i+1]; sum+=a[i]; a[i+1]=-1; sort(a,a+n); for(i=0;i<n;i++) { a[i]=a[i+1]; } n--; } printf("%d",sum); return 0; }
BASIC-29 VIP试题 高精度加法
问题描述
输入两个整数a和b,输出这两个整数的和。a和b都不超过100位。
算法描述
由于a和b都比较大,所以不能直接使用语言中的标准数据类型来存储。对于这种问题,一般使用数组来处理。
定义一个数组A,A[0]用于存储a的个位,A[1]用于存储a的十位,依此类推。同样可以用一个数组B来存储b。
计算c = a + b的时候,首先将A[0]与B[0]相加,如果有进位产生,则把进位(即和的十位数)存入r,把和的个位数存入C[0],即C[0]等于(A[0]+B[0])%10。然后计算A[1]与B[1]相加,这时还应将低位进上来的值r也加起来,即C[1]应该是A[1]、B[1]和r三个数的和.如果又有进位产生,则仍可将新的进位存入到r中,和的个位存到C[1]中。依此类推,即可求出C的所有位。
最后将C输出即可。
输入格式
输入包括两行,第一行为一个非负整数a,第二行为一个非负整数b。两个整数都不超过100位,两数的最高位都不是0。
输出格式
输出一行,表示a + b的值。
样例输入
20100122201001221234567890
2010012220100122
样例输出
20100122203011233454668012
大数加法,相当于在字符串里模仿加法运算法则。
#include<iostream> #include<cstring> int main(void){ char a[105],b[105],c[105]; scanf("%s%s",a,b); memset(c,0,sizeof(c)); int len1=strlen(a); int len2=strlen(b); for(int i=0;i<len1||i<len2;i++){ //将a+b放到c中 if(i<len1) c[i]+=a[len1-1-i]-'0'; if(i<len2) c[i]+=b[len2-1-i]-'0'; if(c[i]>=10) { int t=c[i]%10; c[i+1]=c[i]/10; c[i]=t; } } if(len1<len2) len1=len2; if(c[len1]>0) printf("%d",c[len1]); for(int i=len1-1;i>=0;i--){ printf("%d",c[i]); } printf("\n"); return 0; }
BASIC-30 VIP试题 阶乘计算
问题描述
输入一个正整数n,输出n!的值。
其中n!=123*…*n。
算法描述
n!可能很大,而计算机能表示的整数范围有限,需要使用高精度计算的方法。使用一个数组A来表示一个大整数a,A[0]表示a的个位,A[1]表示a的十位,依次类推。
将a乘以一个整数k变为将数组A的每一个元素都乘以k,请注意处理相应的进位。
首先将a设为1,然后乘2,乘3,当乘到n时,即得到了n!的值。
输入格式
输入包含一个正整数n,n<=1000。
输出格式
输出n!的准确值。
样例输入
10
样例输出
3628800
与上一题类似,乘法复杂一些,注意考虑进位的问题
#include<cstdio> void f(int n) { if(n==1) printf("1\n"); else { int a[100000],tail=0,head=0,p=0; a[0]=1; for(int i=2; i<=n; i++) { for(int j=head; j<=tail; j++) { p=a[j]*i+p; a[j]=p%10; p=p/10; } while(p!=0) { tail++; a[tail]=p%10; p=p/10; } } for(int i=tail; i>=0; i--) printf("%d",a[i]); } } int main() { int n; scanf("%d",&n); f(n); return 0; }