***需要历年机试题(09-22年,持续更新)
A.钥匙
此题尚未公开(对应EOJ的3919题)题目大概意思:给你一串n个环形钥匙,开门时,按照顺序一一试,求第k次试成功后试错了多少次。
eg:
输入:4 6
4 2 1 3
输出:
13
第一次:4 2 1试错2次
第二次:1 3 4 2试错3次
第三次:2 1 3试错2次
第四次:3 4试错1次
第五次:4 2 1试错2次
第六次:1 3 4 2试错3次
共试错:2+3+2+1+2+3=13次
思路:初始时,使用map保存第i个输入编号钥匙对应的第i个门,开启第i个门时(第一次除外)错次数为:(m[i]-m[i-1]+n)% n。第一个门试错次为:(m[1]-first+n)%n。其中first为第一个输入钥匙编号。
第一轮结束之后,第n个钥匙此时在第n个门上,以后每一轮均是如此,因此从第二轮开始试错次数为循环。一轮循环次数也按照上述方法求解,不过此时的钥匙顺序要变为以第n个门对应第n个钥匙为重新映射。
#include<bits/stdc++.h>
using namespace std;
int main() {
map<int,int>m;
int n,k;
cin>>n>>k;
int first;
int a[n+1];
for(int i = 1; i <= n; i++) {
cin>>a[i];
m[a[i]]=i;
if(i == 1)
first = a[1];
}
long long sum = 0;
for(int i = 1; i <= n; i++) {
if(i == 1)
sum += (m[i]-m[first]+n)%n;
else
sum +=(m[i]-m[i-1]+n)%n;
}
int index = n - m[n];
for(int i = 1; i <= n; i++) {
int c = (i+index+n)%n;
if(c==0)
c=n;
m[c]=a[i];
}
int error[n+1];
long long sum1=0;
for(int i = 1; i <= n; i++) {
int er;
if(i == 1)
er = (m[i]-m[n]+n)%n;
else
er=(m[i]-m[i-1]+n)%n;
sum1+=er;
error[i]=er;
}
sum += (k-n)/n*sum1;
for(int i = 1; i <= (k-n)%n; i++)
sum+=error[i];
cout<<sum;
return 0;
}
B.上古计算机
EOJ 854题
单点时限: 2.0 sec
内存限制: 512 MB
Smith有一台古老的计算机,这台计算机使用一套非常特殊的标记编程语言。现在我们仅考虑这一语言的一个小的子集,该子集可以实现一个简单计算器。
这台机器一共有 4 个无差别的寄存器,分别为 AX, BX, CX, DX,在指令中他们可以互相替代,下面的表格列出了所有支持的指令。
例如:以下代码实现表达式 (2+3*5)/6的计算并输出计算结果。
IN AX,3
IN BX,5
MUL AX,BX
IN CX,2
ADD CX,AX
IN BX,6
DIV CX,BX
OUT CX
输入用这种特殊标记编程语言编写的一段代码,请编写一个翻译器,对代码进行翻译,输出最后运行结果。
输入格式
输入代码片段。
注意:读的数据均为int型整数。所有被计算的数值(包括中间值)均保证在int范围内。
输入保证不包含任何多余的空白字符,在开始执行前,所有寄存器的值可以视为已经清零。
对于 30% 的数据指令数 <= 50;
对于 80% 的数据指令数 <= 100 000 ;
对于 100% 的数据指令数 <= 500 000 ;
输出格式
对于每个 OUT 指令,输出一行表示结果。
样例
输入:
IN AX,3
IN BX,5
MUL AX,BX
IN CX,2
ADD CX,AX
IN BX,6
DIV CX,BX
OUT CX
输出:
2
思路:if模拟就行
#include<bits/stdc++.h>
using namespace std;
int fun(string s)
{
int m = 0;
int i = 0;
if(s[0] == '-') //注意有负数
i++;
for(; i < s.size(); i++)
m = m * 10 + s[i] - '0';
if(s[0] == '-')
m *= -1;
return m;
}
int main() {
string c;
map<string,int>m;
while(cin>>c) {
string s;
cin>>s;
if(c=="IN") {
m[s.substr(0,2)]=atoi(s.substr(3,s.size()).c_str());//机房使用的是fun(s.substr(3,s.size()))
} else if(c=="MOV") {
m[s.substr(0,2)]=m[s.substr(3,5)];
} else if(c=="ADD") {
m[s.substr(0,2)]+=m[s.substr(3,5)];
} else if(c=="SUB") {
m[s.substr(0,2)]-=m[s.substr(3,5)];
} else if(c=="MUL") {
m[s.substr(0,2)]*=m[s.substr(3,5)];
} else if(c=="DIV") {
m[s.substr(0,2)]/=m[s.substr(3,5)];
} else {
cout<<m[s]<<endl;
}
}
}
在机房忘记了string转int函数stoi()和atoi(),手写一个函数,结果怎是提交不通过,导致很郁闷,直接影响我后面思路。
C.安全驾驶
EOJ 856题
单点时限: 2.0 sec
内存限制: 512 MB
在一单行直线测试车道中有 辆自动驾驶的小车同向行驶。初始时每辆小车有各自的出发位置和恒定速度。
同时开始出发后,若后面的小车追上前面的小车,为了安全则必须降速到与前车相同的速度。最后所有小车都需要到达目的地。
最后一辆小车不想中途降速,希望全程匀速行驶,请找出最后一辆小车在满足条件(全程匀速且保证安全)的情况下最大可能的速度。
输入格式
第一行包含一个正整数 d km( 1<= d <= 10^9)表示最后一辆车目前离目的地的位置。
第二行包含一个正整数 n(1<= n <= 1000)表示除最后一辆车外小车的数量。
第 i+2行包含两个以空格分隔的正整数,表示第 i 辆小车在最后一辆小车前方的距离 k km,以及他的速度 v km/h,保证所有小车的出发位置各不相同。
输出格式
一行中输出最后一辆车的最大的可能速度(单位为 km/h),保留 6位小数。
样例
输入:
2525
1
2400 5
输出:
101.000000
输入:
300
2
120 60
60 90
输出:
100.000000
输入:
100
2
80 100
70 10
输出:
33.333333
思路:只要计算距离最近一辆车到达终点时间就行,而每一辆车到达终点时间t1均取决于前一辆车到达终点的时间t2,即t1=max(t1,t2)。
#include<bits/stdc++.h>
using namespace std;
struct node {
double x,v;
double t;
};
bool cmp(node a,node b) {
return a.x < b.x;
}
int main() {
int s;
int n;
cin>>s>>n;
vector<node>v;
for(int i = 0; i < n; i++) {
node d;
cin>>d.x>>d.v;
v.push_back(d);
}
sort(v.begin(),v.end(),cmp);
v[n-1].t = (s-v[n-1].x)/v[n-1].v;
for(int i = v.size()-2; i >= 0; i--) {
double t2 = (s-v[i].x)/v[i].v;
double t1 = v[i+1].t;
v[i].t=max(t1,t2);
}
printf("%.6f",s/v[0].t);
}
或者求前面达到终点的最大时间t,就是他到达终点的时间。
s,n = map(int,input().split())
t = 0.0
for i in range(n):
x,v = map(int,input().split())
t = max((s-x)/v,t)
print("{:.6f}".format(s/t))
D.表面积
单点时限: 1.0 sec
内存限制: 512 MB
在 n 个圆柱体中挑选 k个,按照半径从大到小圆心对齐叠在一起放在地面上(最大的一个在最下面),计算可能的最大可视表面积。
输入格式
第 1 行:整数 n和 k,一个空格分隔。
第 n+1行:每个圆柱体的半径 Rcm与高度 Hcm,一个空格分隔。
输出格式
一行中输出。表示可能的最大表面积为 乘以圆周率的cm2 。
样例
输入:
2 1
100 20
200 10
输出:
44000
输入:
3 2
100 10
100 10
100 10
输出:
14000
输入:
4 2
9 3
7 1
10 1
8 4
输出:
199
思路:按照表面积大小从大到小排列,以第i个圆柱作为第一个,则再挑选出k-1个圆柱就行。此时的可视表面积为k个主视图面积加上最底下面圆柱的一个底面积。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct node
{
ll r,h,s;
}a[1001];
bool cmp(node x,node y)
{
return x.s > y.s;
}
int main()
{
int n, m;
cin>>n>>m;
for (int i = 1; i <= n; i++)
{
cin>>a[i].r>>a[i].h;
a[i].s = 2 * a[i].r * a[i].h;
}
sort(a + 1, a + n + 1,cmp);
ll res = 0;
for (int i = 1; i <= n; i++)
{
ll sum = a[i].s + a[i].r*a[i].r;
int count = 1;
for (int j = 1; j <= n && count < m; j++)
{
if (i == j || a[j].r > a[i].r) continue;
sum += a[j].s;
count++;
}
if (count == m)
res = max(res, sum);
}
cout<<res<<endl;
return 0;
}
E.达到回文数
EOJ 2851题
单点时限: 2.0 sec
内存限制: 256 MB
整数 n (1 <= n <= 10000),从右往左读得到它的反数 m,判断 n与 m 的和 s 是否是一个回文数。回文数是从左往右读和从右往左读结果一样的整数。若 s 不是一个回文数,则继续判断 和它的反数的和是否是一个回文数。重复这一过程,直至达到和为一个回文数为止。
例如, n 为 195 ,则 m 为 591 , s 为 786;再计算 786 + 687 = 1473;1473 + 3741 = 5214 ;5214 + 4125 = 9339 。在达到回文数 9339 之前总共进行了 4 次加法操作。
对于 n,要求计算出达到回文数之前所进行的加法操作的最小次数和最终达到的回文数。
n 本身不是一个回文数。保证对于 n 来说一定能在 10000 次加法操作之前达到回文数,并且在计算过程中的和一定小于200000000 。
输入格式
由一个整数 n 组成的一行信息。
输出格式
一行信息,用一个空格分隔的最小加法次数及最终达到的回文数。
样例:
输入:
195
输出:
4 9939
思路:签到题,简单模拟
n = input()
m = n[::-1]
count = 0
while(n != m):
s = int(n) + int(m)
n = str(s)
m = n[::-1]
count += 1
print(count,n)