第一次做这种试卷,提交了才发现原来就算你全AC了,提交次数多的话也会扣你分==直接上题,注释我认为很多了.代码全部用C++完成.
[编程题]
1.回文序列
如果一个数字序列逆置之后跟原序列是一样的就称这样的数字序列为回文序列。例如:
{1, 2, 1}, {15, 78, 78, 15} , {112} 是回文序列,
{1, 2, 2}, {15, 78, 87, 51} ,{112, 2, 11} 不是回文序列。
现在给出一个数字序列,允许使用一种转换操作:
选择任意两个相邻的数,然后从序列移除这两个数,并用这两个数字的和插入到这两个数之前的位置(只插入一个和)。
现在对于所给序列要求出最少需要多少次操作可以将其变成回文序列。
输入描述:
输入为两行,第一行为序列长度n ( 1 ≤ n ≤ 50)
第二行为序列中的n个整数item[i] (1 ≤ iteam[i] ≤ 1000),以空格分隔。
输出描述:
输出一个数,表示最少需要的转换次数
输入例子:
4
1 1 1 3
输出例子:
2
#include <iostream>
#include <cstdio>
using namespace std;
int n, _beg, _end, sum, item[1010];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&item[i]);
_beg = 1; _end = n;
while(_beg < _end)
{
if(item[_beg] == item[_end])//首尾相同
{
_beg++; _end--;
}
else if(item[_beg] > item[_end])//首比尾大
{
item[_end-1] += item[_end];
_end--; sum++;
}
else
{
item[_beg+1] += item[_beg];
_beg++; sum++;
}
}
printf("%d\n",sum);
return 0;
}
///
[编程题]
2.优雅的点
小易有一个圆心在坐标原点的圆,小易知道圆的半径的平方。小易认为在圆上的点而且横纵坐标都是整数的点是优雅的,小易现在想寻找一个算法计算出优雅的点的个数,请你来帮帮他。
例如:半径的平方如果为25
优雅的点就有:(+/-3, +/-4), (+/-4, +/-3), (0, +/-5) (+/-5, 0),一共12个点。
输入描述:
输入为一个整数,即为圆半径的平方,范围在32位int范围内。
输出描述:
输出为一个整数,即为优雅的点的个数
输入例子:
25
输出例子:
12
//优雅的点
#include <iostream>
#include <cmath>
#include <cstdio>
using namespace std;
int r, sum, _up, temp;
int main()
{
scanf("%d",&r);
_up = sqrt(r);
for(int i=0;i<=_up;i++)
{
temp = i*i;
int j = sqrt(r-temp);
if(temp + j*j == r)
{
if(i==0 || j==0)
sum += 2;
else
sum += 4;
}
}
printf("%d\n",sum);
return 0;
}
///
[编程题]
3.跳石板
小易来到了一条石板路前,每块石板上从1挨着编号为:1、2、3.......
这条石板路要根据特殊的规则才能前进:对于小易当前所在的编号为K的 石板,小易单次只能往前跳K的一个约数(不含1和K)步,即跳到K+X(X为K的一个非1和本身的约数)的位置。 小易当前处在编号为N的石板,他想跳到编号恰好为M的石板去,小易想知道最少需要跳跃几次可以到达。
例如:
N = 4,M = 24:
4->6->8->12->18->24
于是小易最少需要跳跃5次,就可以从4号石板跳到24号石板
输入描述:
输入为一行,有两个整数N,M,以空格隔开。
(4 ≤ N ≤ 100000)
(N ≤ M ≤ 100000)
输出描述:
输出小易最少需要跳跃的步数,如果不能到达输出-1
输入例子:
4 24
输出例子:
5
/*
跳石版
用 res 保存到当前这个石板所需的最小步数,再从 res 向后更新后面的石板
*/
#include <iostream>
#include <math.h>
#include <stdio.h>
using namespace std;
int N, M, temp;
int res[110000];
int main()
{
scanf("%d%d",&N,&M);
if(N == M)//特判
{
cout<<0<<endl;
return 0;
}
for(int i=N;i<=M;i++)
{
if(i>N && res[i] == 0)//不能到这个板子,就没有后面的讨论
continue;
for(int j=2;j<=sqrt(i) && i+j<=M;j++)
{
if(i%j == 0)
{
if(res[i+j] == 0)//未能走到过
{
res[i+j] = res[i]+1;
}
else
{
if(res[i]+1 < res[i+j])
res[i+j] = res[i]+1;
}
temp = i/j;
if(i+temp <=M && temp!=j)
{
if(res[i+temp] == 0)//未能走到过
{
res[i+temp] = res[i]+1;
}
else
{
if(res[i]+1 < res[i+temp])
res[i+temp] = res[i]+1;
}
}
}
}
}
if(res[M])
printf("%d\n",res[M]);
else
printf("-1\n");
return 0;
}
///
[编程题]
4.暗黑的字符串
一个只包含'A'、'B'和'C'的字符串,如果存在某一段长度为3的连续子串中恰好'A'、'B'和'C'各有一个,那么这个字符串就是纯净的,否则这个字符串就是暗黑的。例如:
BAACAACCBAAA 连续子串"CBA"中包含了'A','B','C'各一个,所以是纯净的字符串
AABBCCAABB 不存在一个长度为3的连续子串包含'A','B','C',所以是暗黑的字符串
你的任务就是计算出长度为n的字符串(只包含'A'、'B'和'C'),有多少个是暗黑的字符串。
输入描述:
输入一个整数n,表示字符串长度(1 ≤ n ≤ 30)
输出描述:
输出一个整数表示有多少个暗黑字符串
输入例子:
2
3
输出例子:
9
21
/*
暗黑的字符串
纯净的字符串:随便选个三连位,其余部分是暗黑字符串。
same[n]:最后两位相同
diff[n]:最后两位不同
从 same[n] 生成 n+1:
{
1.最后两位相同: same[n]
2.最后两位不同: 2*same[n];
}
从 diff[n] 生成 n+1:
{
1.最后两位相同: diff[n]
2.最后两位不同: diff[n];
}
num[n+1] = 2*diff[n] + 3*same[n];
*/
//坑爹的是,要改成 long 否则结果会被截断
#include <iostream>
#include <math.h>
#include <stdio.h>
using namespace std;
long n, sum[40];//一共有 sum 种
void dark(long n)
{
if(n==1 || n==2)
{
return;
}
long s = 3, d = 6;
int len = 2;
while(len < n)
{
sum[len+1] = 2*d+3*s;
len += 1;
long tp1 = s, tp2 = d;
s = tp1+tp2;
d = tp2+2*tp1;
}
}
int main()
{
sum[1] = 3;
sum[2] = 9;
scanf("%ld",&n);
dark(n);
printf("%ld\n",sum[n]);
return 0;
}
///
[编程题]
5.数字翻转
对于一个整数X,定义操作rev(X)为将X按数位翻转过来,并且去除掉前导0。例如:
如果 X = 123,则rev(X) = 321;
如果 X = 100,则rev(X) = 1.
现在给出整数x和y,要求rev(rev(x) + rev(y))为多少?
输入描述:
输入为一行,x、y(1 ≤ x、y ≤ 1000),以空格隔开。
输出描述:
输出rev(rev(x) + rev(y))的值
输入例子:
123 100
输出例子:
223
/*
数字翻转
*/
#include <iostream>
#include <string.h>
#include <math.h>
#include <stdio.h>
using namespace std;
char x[100], y[100], res[100], str[100], ta[100], tb[100];
void _plus(char a[100],char b[100])
{
int l1 = strlen(a), l2 = strlen(b);
if(a[0] == '0')
{
for(int i=0;i<l2;i++)
res[i] = b[l2-i-1];
return;
}
if(b[0] == '0')
{
for(int i=0;i<l1;i++)
res[i] = a[l1-i-1];
return;
}
for(int i=l1-1;i>=0;i--)
{
if(a[i] != '0')
break;
a[i] = '\0';
}
for(int i=l2-1;i>=0;i--)
{
if(b[i] != '0')
break;
b[i] = '\0';
}
//以上为去掉 a 和 b 的后缀0
int la = strlen(a), lb = strlen(b);
for(int i=0;i<la;i++)
ta[i] = a[la-i-1];
for(int i=0;i<lb;i++)
tb[i] = b[lb-i-1];
//完成翻转
int aa[100] = {}, bb[100] = {};
//转化成整型
for(int i=0;i<la;i++)
{
aa[i] = ta[la-i-1]-'0';
}
for(int i=0;i<lb;i++)
{
bb[i] = tb[lb-i-1]-'0';
}
int mmax = max(la,lb);
for(int i=0;i<mmax;i++)
{
aa[i] += bb[i];
if(aa[i] >= 10)
{
aa[i+1] += aa[i]/10;//这里写成 a 了,一直错。
aa[i] %= 10;
if(i == mmax-1)
{
mmax += 1;
}
}
}
for(int i=0;i<mmax;i++)
{
res[i] = aa[mmax-i-1]+'0';
}
res[mmax] ='\0';
}
int main()
{
//scanf("%s%s",&x,&y);
cin>>x>>y;
_plus(x,y);//rex(x)+rex(y)
//cout<<res<<endl;
int len = strlen(res);
for(int i=len-1;i>=0;i--)
{
if(res[i] != '0')
break;
res[i] = '\0';
}
len = strlen(res);
for(int i=0;i<len;i++)
str[len-i-1] = res[i];
cout<<str<<endl;
return 0;
}
///
[编程题]
6.最大的奇约数
小易是一个数论爱好者,并且对于一个数的奇数约数十分感兴趣。一天小易遇到这样一个问题: 定义函数f(x)为x最大的奇数约数,x为正整数。 例如:f(44) = 11.
现在给出一个N,需要求出 f(1) + f(2) + f(3).......f(N)
例如: N = 7
f(1) + f(2) + f(3) + f(4) + f(5) + f(6) + f(7) = 1 + 1 + 3 + 1 + 5 + 3 + 7 = 21
小易计算这个问题遇到了困难,需要你来设计一个算法帮助他。
输入描述:
输入一个整数N (1 ≤ N ≤ 1000000000)
输出描述:
输出一个整数,即为f(1) + f(2) + f(3).......f(N)
输入例子:
7
输出例子:
21
/*
最大的奇约数
sum(i) = f(1) + f(2) + ... + f(i);
对于奇数, f(i) = i;
对于偶数, f(2k) = f(k)
f(2) + f(4) + ... + f(2k) = f(1) +f(2) + ... + f(k)
所以 sum(2k) = f(1)+f(2)+f(3)+...+f(2k) = sum(k) + 1+3+5+7+...+(2k-1);
即 sum(k) = sum(k/2)+k*k/4;(k为偶数)
*/
#include <iostream>
#include <string.h>
#include <math.h>
#include <stdio.h>
using namespace std;
long n;
long sum(long x)
{
if(x == 1)
return 1;
if(x == 2)
return 2;
if(x % 2 == 1)//奇数
return sum(x-1)+x;
else
return sum(x/2)+x*x/4;
}
int main()
{
cin>>n;
cout<<sum(n)<<endl;
return 0;
}
///
[编程题]
7.买苹果
小易去附近的商店买苹果,奸诈的商贩使用了捆绑交易,只提供6个每袋和8个每袋的包装(包装不可拆分)。 可是小易现在只想购买恰好n个苹果,小易想购买尽量少的袋数方便携带。如果不能购买恰好n个苹果,小易将不会购买。
输入描述:
输入一个整数n,表示小易想购买n(1 ≤ n ≤ 100)个苹果
输出描述:
输出一个整数表示最少需要购买的袋数,如果不能买恰好n个苹果则输出-1
输入例子:
20
输出例子:
3
/*
买苹果
*/
#include <iostream>
#include <string.h>
#include <math.h>
#include <stdio.h>
using namespace std;
int n, flag, res;
int main()
{
cin>>n;
if(n<6)
{
cout<<-1<<endl;
return 0;
}
for(int i=n/8;i>=0;i--)
{
int temp = n-8*i;
if(temp%6 == 0)//剩下的是6的倍数
{
flag = 1;
res = i+(temp/6);
break;
}
}
if(flag == 0)
cout<<-1<<endl;
else
cout<<res<<endl;
return 0;
}
///
[编程题]
8.计算糖果
A,B,C三个人是好朋友,每个人手里都有一些糖果,我们不知道他们每个人手上具体有多少个糖果,但是我们知道以下的信息:
A - B, B - C, A + B, B + C. 这四个数值.每个字母代表每个人所拥有的糖果数.
现在需要通过这四个数值计算出每个人手里有多少个糖果,即A,B,C。这里保证最多只有一组整数A,B,C满足所有题设条件。
输入描述:
输入为一行,一共4个整数,分别为A - B,B - C,A + B,B + C,用空格隔开。
范围均在-30到30之间(闭区间)。
输出描述:
输出为一行,如果存在满足的整数A,B,C则按顺序输出A,B,C,用空格隔开,行末无空格。
如果不存在这样的整数A,B,C,则输出No
输入例子:
1 -2 3 4
输出例子:
2 1 3
/*
计算糖果
*/
#include <iostream>
#include <string.h>
#include <math.h>
#include <stdio.h>
using namespace std;
int a, b, c, d, flag;
int main()
{
cin>>a>>b>>c>>d;
for(int i=0;i<=30;i++)//枚举 A
{
int j = i-a;
int k = i-a-b;
if(j>=0 && k>=0)
{
if(i+j == c)
{
if(j+k == d)
{
flag = 1;
cout<<i<<" "<<j<<" "<<k<<endl;
break;
}
}
}
}
if(!flag)
cout<<"No"<<endl;
return 0;
}