BASIC-3 基础练习 字母图形
问题描述
利用字母可以组成一些美丽的图形,下面给出了一个例子:
ABCDEFG
BABCDEF
CBABCDE
DCBABCD
EDCBABC
这是一个5行7列的图形,请找出这个图形的规律,并输出一个n行m列的图形。
输入格式
输入一行,包含两个整数n和m,分别表示你要输出的图形的行数的列数。
输出格式
输出n行,每个m个字符,为你的图形。
样例输入
5 7
样例输出
ABCDEFG
BABCDEF
CBABCDE
DCBABCD
EDCBABC
数据规模与约定
1 <= n, m <= 26。
思路: i == j 的位置永远是 ‘A’ 。在该位置右边,即 j > i 时,是从左到右递增的字母序列;在该位置左边,即 j < i ,是从右到左递增的字母序列。所以,字母的序号与两个坐标的差的绝对值有关。
C++ Code:
#include <iostream>
#include <cmath>
using namespace std;
char a[30][30];
int main(){
int n,m; cin>>n>>m;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++)
cout<<char('A'+abs(j-i));
cout<<endl;
}
return 0;
}
Java Code:
import java.util.Scanner;
import java.math.*;
public class Main {
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
int n = cin.nextInt();
int m = cin.nextInt();
for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++)
System.out.print((char)('A'+Math.abs(i-j)));
System.out.println();
}
}
}
BASIC-14 基础练习 时间转换
问题描述
给定一个以秒为单位的时间t,要求用 “< H > : < M > : < S >”的格式来表示这个时间。< H > 表示时间,< M > 表示分钟,而 < S > 表示秒,它们都是整数且没有前导的“0”。例如,若t=0,则应输出是“0:0:0”;若t=3661,则输出“1:1:1”。
输入格式
输入只有一行,是一个整数t(0<=t<=86399)。
输出格式
输出只有一行,是以“ < H > : < M > : < S > ”的格式所表示的时间,不包括引号。
样例输入
0
样例输出
0:0:0
样例输入
3661
样例输出
1:1:1
样例输入
5436
样例输出
1:30:36
思路: 水题,直接取余即可。
Java Code:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner cin = new Scanner(System.in);
int t = cin.nextInt();
int y = t / 3600;
t = t % 3600;
int m = t / 60;
t = t % 60;
int s = t;
System.out.println(y + ":" + m + ":" + s);
}
}
BASIC-15 基础练习 字符串对比
问题描述
给定两个仅由大写字母或小写字母组成的字符串(长度介于1到10之间),它们之间的关系是以下4中情况之一:
1:两个字符串长度不等。比如 Beijing 和 Hebei
2:两个字符串不仅长度相等,而且相应位置上的字符完全一致(区分大小写),比如 Beijing 和 Beijing
3:两个字符串长度相等,相应位置上的字符仅在不区分大小写的前提下才能达到完全一致(也就是说,它并不满足情况2)。比如 beijing 和 BEIjing
4:两个字符串长度相等,但是即使是不区分大小写也不能使这两个字符串一致。比如 Beijing 和 Nanjing
编程判断输入的两个字符串之间的关系属于这四类中的哪一类,给出所属的类的编号。
输入格式
包括两行,每行都是一个字符串
输出格式
仅有一个数字,表明这两个字符串的关系编号
样例输入
BEIjing
beiJing
样例输出
3
思路: 直接用 Java 的Api 。
Java Code:
import java.util.Scanner;
public class Main {
static int[] ans = new int[10];
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner cin = new Scanner(System.in);
String s1 = cin.next();
String s2 = cin.next();
if(s1.length() != s2.length())
System.out.println(1);
else {
if(s1.equals(s2))
System.out.println(2);
else {
if(s1.toLowerCase().equals(s2.toLowerCase()))
System.out.println(3);
else
System.out.println(4);
}
}
}
}
BASIC-16 基础练习 分解质因数
问题描述
求出区间[a,b]中所有整数的质因数分解。
输入格式
输入两个整数a,b。
输出格式
每行输出一个数的分解,形如k=a1a2a3…(a1<=a2<=a3…,k也是从小到大的)(具体可看样例)
样例输入
3 10
样例输出
3=3
4=22
5=5
6=23
7=7
8=222
9=33
10=25
提示
先筛出所有素数,然后再分解。
数据规模与约定
2<=a<=b<=10000
思路: 这道题跟 蓝桥杯1137 算法提高 质因数 那道题几乎一样,只不过这道题多了一个区间。直接遍历到 sqrt(n) ,如果 n 不是素数且 n 存在质数 i ,则输出该质数,同时 n/=i,此时 i-- ,为了输出所有相同的质数。
Java Code:
import java.util.Scanner;
public class Main {
static boolean isprime(int n) {
for(int i=2;i*i<=n;i++) {
if(n%i==0) return false;
}
return true;
}
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
int a = cin.nextInt();
int b = cin.nextInt();
for(int i=a;i<=b;i++) {
System.out.print(i+"=");
int x=i;
for(int j=2;j*j<=x && !isprime(x);j++) {
if(isprime(j) && x%j==0) {
System.out.print(j+"*");
x/=j;
j--;
}
}
System.out.println(x);
}
}
}
BASIC-17 基础练习 矩阵乘法
问题描述
给定一个N阶矩阵A,输出A的M次幂(M是非负整数)
例如:
A =
1 2
3 4
A的2次幂
7 10
15 22
输入格式
第一行是一个正整数N、M(1<=N<=30, 0<=M<=5),表示矩阵A的阶数和要求的幂数。接下来N行,每行N个绝对值不超过10的非负整数,描述矩阵A的值
输出格式
输出共N行,每行N个整数,表示A的M次幂所对应的矩阵。相邻的数之间用一个空格隔开
样例输入
2 2
1 2
3 4
样例输出
7 10
15 22
思路: 可以分为三种情况,0 次幂、1次幂、2次幂及以上。任意矩阵的 0 次幂肯定是单位矩阵,1次幂就是矩阵本身,2次幂及以上就要进行 m 次运算,具体见代码。
Java Code:
import java.util.Scanner;
public class Main {
static int[][] a = new int[35][35];
static int[][] b = new int[35][35];
static int[][] t = new int[35][35];
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
int n = cin.nextInt();
int m = cin.nextInt();
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) {
a[i][j] = cin.nextInt();
b[i][j] = a[i][j];
}
if(m==0) { //矩阵的0次幂为单位矩阵
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++) {
if(i==j) System.out.print(1+" ");
else System.out.print(0+" ");
}
System.out.println();
}
System.out.println();
System.exit(0);
}
if(m==1) { //矩阵的1次幂为其本身
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++)
System.out.print(a[i][j]+" ");
System.out.println();
}
System.out.println();
System.exit(0);
}
while(m>=2) { //矩阵2次幂及以上需要运算m次
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++) {
int k=n;
while(k>0) {
t[i][j] += b[i][k]*a[k][j];
k--;
}
}
}
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++) {
b[i][j]=t[i][j];
t[i][j]=0;
}
}
m--;
}
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++) {
System.out.print(b[i][j]+" ");
}
System.out.println();
}
System.out.println();
}
}
BASIC-19 基础练习 完美的代价
问题描述
回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
交换的定义是:交换两个相邻的字符
例如mamad
第一次交换 ad : mamda
第二次交换 md : madma
第三次交换 ma : madam (回文!完美!)
输入格式
第一行是一个整数N,表示接下来的字符串的长度(N <= 8000)
第二行是一个字符串,长度为N.只包含小写字母
输出格式
如果可能,输出最少的交换次数。
否则输出Impossible
样例输入
5
mamad
样例输出
3
思路:
1. 出现“impossible” 的两种情况:
(1)字符串是偶数长度,且有一个奇数个数的字符,那么不可能构成回文串。
(2)有两个及两个以上奇数个数的字符且字符串长度为奇数,也不可能构成回文串。
2. 最小交换次数的情况:
(1)如果 n 为偶数,那么从第一字符开始,从后往前找第一个和它相同的字符,如果找了,就将找到的字符交换到最后一个位置,同时累加每次交换的次数。在下一次遍历时,从第二个字符开始,从倒数第二个字符开始遍历,执行和上述相同的操作;
(2)如果 n 为奇数,在字符串的某一个位置找到了那个出现次数为奇数的字符,先计算它到中间位置需要交换的次数,然后累加到 cnt 中,将剩下的字符都交换到对称后,再交换这个字符即可。
C++ Code:
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int main(){
ios::sync_with_stdio(0);
int n; cin>>n;
string str; cin>>str;
int sum=0; //sum统计交换的次数
int vis=0; //vis判断是否已经有一个奇数个数的字符
int k=n-1; //暂存
for(int i=0;i<k;i++){ //左指针遍历到第二个字符
for(int j=k;j>=i;j--){ //右指针遍历到i
if(j==i){ //如果找不到相同的字符
//如果字符串偶数长度且有一个奇数个数的字符 或者 有两个及两个以上的奇数个数的字符且字符串长度为奇数
if( !(n%2) || vis ){
cout<<"Impossible"<<endl;
return 0;
}
vis=1; //标记
sum+=(n/2-i); //奇数个数字符移到中间的步数
}
else if(str[j]==str[i]){ //如果找到相同字符
for(int t=j;t<k;t++){
swap(str[t],str[t+1]); //把str[j]换到str[k]
sum++; //每交换一次,计数一次
}
k--; //右指针左移
break;
}
}
}
cout<<sum<<endl;
return 0;
}
Java Code:
import java.util.Scanner;
public class Main {
static char[] s;
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
int n = in.nextInt();
in.nextLine();
s = in.nextLine().toCharArray();
in.close();
int cnt=0;
int k=n-1;
boolean vis = false;
for(int i=0;i<n;i++) {
for(int j=k;j>=i;j--) {
if(j==i) {
if(n%2==0 || vis) {
System.out.println("Impossible");
return;
}
vis = true;
cnt += (n/2-i);
}
else if(s[i]==s[j]) {
for(int t=j;t<k;t++) {
swap(t,t+1);
cnt++;
}
k--;
break;
}
}
}
System.out.println(cnt);
}
private static void swap(int x,int y) {
char temp = s[x];
s[x] = s[y];
s[y] = temp;
}
}
BASIC-21 基础练习 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
思路: 这道题有两种做法,可以暴力模拟,也可以按规律来递归调用。
1. 暴力做法就是直接遍历从左到右输出字符串。
2. 用规律来递归调用:
(1)先出现的是左括号
(2)然后出现的是An
(3)然后出现的是加减号
(4)接着出现的是 一个有规律的数 m-i+1
(5)最后出现的是右括号(最后一个数除外,即最后一个不包含右括号)
C++ Code1: 暴力模拟
#include <iostream>
using namespace std;
int main(){
int n; cin>>n;
for(int i=1;i<n;i++)
cout<<"(";
for(int i=1;i<=n;i++){
if(i==1)
cout<<"sin(1)";
else{
cout<<"sin(1-sin(2";
for(int j=3;j<=i;j++){
if(j%2==0)
cout<<"-";
else
cout<<"+";
cout<<"sin("<<j;
}
for(int j=1;j<=i;j++)
cout<<")";
}
cout<<"+"<<n-i+1;
if(i!=n)
cout<<")";
}
}
C++ Code2: 递归做法
#include <iostream>
using namespace std;
void An(int k){ //输出An
for(int i=1;i<=k;i++){
cout<<"sin("<<i;
if(i==k)
break;
else{
if(i%2==1)
cout<<"-";
else
cout<<"+";
}
}
for(int i=1;i<=k;i++)
cout<<")";
}
void Sn(int m){ //输出Sn
for(int i=1;i<m;i++)
cout<<"(";
for(int i=1;i<=m;i++){
An(i);
cout<<"+"<<m-i+1;
if(i!=m)
cout<<")";
}
}
int main(){
int n; cin>>n;
Sn(n);
return 0;
}
BASIC-22 基础练习 FJ的字符串
问题描述
FJ在沙盘上写了这样一些字符串:
A1 = “A”
A2 = “ABA”
A3 = “ABACABA”
A4 = “ABACABADABACABA”
… …
你能找出其中的规律并写所有的数列AN吗?
输入格式
仅有一个数:N ≤ 26。
输出格式
请输出相应的字符串AN,以一个换行符结束。输出中不得含有多余的空格或换行、回车符。
样例输入
3
样例输出
ABACABA
思路: 这种找规律题一定不要自己像规律,很容易就把题意想错,应该多运行几个结果找规律。
从结果显示可以发现规律:
第一个为A,
第二个在A的基础上加上B,再加第一个 ,即ABA
第三个在第二个的基础上加上C,再加第二个,即ABACABA
注意:输出 ‘A’+x-1 时不要用 cout 输出格式,会输出数字,应该用 printf 输出格式。
C++ Code:
#include <iostream>
#include <cstdio>
using namespace std;
void f(int x){
if(x==1)
cout<<'A';
else{
f(x-1);
printf("%c",'A'+x-1);
f(x-1);
}
}
int main(){
int n; cin>>n;
f(n);
return 0;
}
Java Code:
import java.util.Scanner;
public class Main {
public static void f(int x) {
if(x==1)
System.out.print('A');
else {
f(x-1);
System.out.print((char)('A'-1+x));
f(x-1);
}
}
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
f(cin.nextInt());
}
}
BASIC-23 基础练习 芯片测试
问题描述
有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
思路:
- 题意理解:好芯片比坏芯片多,且用好芯片测试其他芯片能正确给出被测试芯片是好还是坏,说明对于每块好芯片,至少有 n/2 块好芯片能测出其是好的,即测出结果为1。
- 那么只要遍历每块被测试芯片,只要满足测试结果为1的数目大于等于 n/2(不包括测试自己的结果)。
- 第 i 行第 j 列的数据表示用第 i 块芯片测试第 j 块芯片,因此每一列的数据表示每块芯片被测试的结果。
C++ Code:
#include <iostream>
#include <algorithm>
using namespace std;
int a[25][25];
int sum[25];
int main(){
int n; cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
cin>>a[i][j];
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i!=j && a[i][j]==1)
sum[j]++;
}
}
for(int j=1;j<=n;j++){
if(sum[j]>=n/2)
cout<<j<<" ";
}
return 0;
}
Java Code:
import java.util.Scanner;
public class Main {
static int[][] a = new int[25][25];
static int[] sum = new int[25];
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
int n = in.nextInt();
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
a[i][j] = in.nextInt();
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i!=j && a[i][j]==1)
sum[j]++;
}
}
for(int j=1;j<=n;j++){
if(sum[j]>=n/2)
System.out.print(j + " ");
}
}
}
BASIC-24 基础练习 龟兔赛跑预测
问题描述
话说这个世界上有各种各样的兔子和乌龟,但是研究发现,所有的兔子和乌龟都有一个共同的特点——喜欢赛跑。于是世界上各个角落都不断在发生着乌龟和兔子的比赛,小华对此很感兴趣,于是决定研究不同兔子和乌龟的赛跑。
他发现,兔子虽然跑比乌龟快,但它们有众所周知的毛病——骄傲且懒惰,于是在与乌龟的比赛中,一旦任一秒结束后兔子发现自己领先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
思路: 这道题需要有较好的思维模拟能力,要不然真的有点乱。
- 当兔子且乌龟都还没到达终点时,分为两种情况,一种就是兔子停下来,判断这时间内乌龟能不能到达终点。一种是兔子不停下来。不断地更新数据。、
- 最后根据乌龟和兔子的路程,输出结果。
- 要注意的一点就是,这道题不需要考虑是否为浮点数。
C++ Code:
#include <iostream>
#include <algorithm>
using namespace std;
int main(){
int v1,v2,t,s,l;
cin>>v1>>v2>>t>>s>>l;
int s1=0,s2=0; //兔子和乌龟的路程
int t0=0; //兔子或乌龟到达终点所用的时间
while(s1<l && s2<l){
if(s1-s2>=t){ //兔子停下来
if((l-s2)/v2 < s){
t0+=(l-s2)/v2;
s2=l;
}else{
s2+=v2*s;
t0+=s;
}
}else{ //兔子不停
t0++;
s1+=v1;
s2+=v2;
}
}
if(s1>s2){
cout<<'R'<<endl;
cout<<t0<<endl;
}else if(s2>s1){
cout<<'T'<<endl;
cout<<t0<<endl;
}else{
cout<<'D'<<endl;
cout<<t0<<endl;
}
return 0;
}
BASIC-25 基础练习 回形取数(模拟)
问题描述
回形取数就是沿矩阵的边取数,若当前方向上无数可取或已经取过,则左转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
思路: 用 while 循环来计算已经输出的数量,然后在这个循环里,以一圈为一个循环,即 “下右上左” 。要用标记数组来标记数是否用过。
Java Code:
import java.util.Scanner;
public class Main {
static int[][] a = new int[210][210];
static int[][] vis = new int[210][210];
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner cin = new Scanner(System.in);
int n = cin.nextInt(), m = cin.nextInt();
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
a[i][j] = cin.nextInt();
int cnt = 1, i = 1, j = 1;
vis[1][1] = 1;
System.out.print(a[1][1] + " ");
while (cnt < n*m) {
while (i + 1 <= n && vis[i+1][j] == 0) {
vis[i+1][j] = 1;
System.out.print(a[i+1][j] + " ");
i++;
cnt++;
}
while (j + 1 <= m && vis[i][j+1] == 0) {
vis[i][j+1] = 1;
System.out.print(a[i][j+1] + " ");
j++;
cnt++;
}
while (i - 1 >= 1 && vis[i-1][j] == 0) {
vis[i-1][j] = 1;
System.out.print(a[i-1][j] + " ");
i--;
cnt++;
}
while (j - 1 >= 1 && vis[i][j-1] == 0) {
vis[i][j-1] = 1;
System.out.print(a[i][j-1] + " ");
j--;
cnt++;
}
}
}
}
BASIC-28 基础练习 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
思路: 运用优先队列的小顶堆做法,当队列的长度大于1,不断把最小的两个数加入总和 ans,并将该两个数删掉后把其和压入队列。
C++ Code:
#include <iostream>
#include <queue>
using namespace std;
int main(){
priority_queue<int,vector<int>,greater<int> > q;
int n; cin>>n;
int x;
for(int i=1;i<=n;i++){
cin>>x;
q.push(x);
}
int ans=0,sum=0;
while(q.size()>1){
ans+=q.top();
sum+=q.top();
q.pop();
ans+=q.top();
sum+=q.top();
q.pop();
q.push(sum);
sum=0;
}
cout<<ans<<endl;
return 0;
}
Java Code:
//优先队列做法
import java.util.PriorityQueue;
import java.util.Scanner;
public class Main {
static PriorityQueue<Integer> q = new PriorityQueue<Integer>();
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
int n = cin.nextInt();
for(int i=0; i<n; i++)
q.offer(cin.nextInt());
int ans=0,sum=0;
while(q.size()>1) {
sum+=q.poll();
sum+=q.poll();
ans+=sum;
q.offer(sum);
sum=0;
}
System.out.println(ans);
}
}
Java Code:
//ArrayList集合做法
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
List<Integer> lst = new ArrayList<Integer>();
Scanner cin = new Scanner(System.in);
int n = cin.nextInt();
for(int i = 1; i <= n; i++)
lst.add(cin.nextInt());
int ans = 0;
while(lst.size() > 1) {
Collections.sort(lst);// 给列表排序
int temp = lst.get(0) + lst.get(1);
lst.set(0, temp);// 用temp替换掉列表里索引为0的元素
lst.remove(1);// 移除下标为1的元素
ans += temp;
}
System.out.println(ans);
}
}
BASIC-29 基础练习 高精度加法
问题描述
输入两个整数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
思路: 高精度题目用 C++ 来做比较麻烦,要将其转换为字符串来处理。用 Java 或者 Python 来处理就很简单了。
C++ Code:
#include <bits/stdc++.h>
using namespace std;
int main()
{
string str1,str2;
int a[250],b[250],len; //数组的大小决定了计算的高精度最大位数
int i;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
cin>>str1>>str2; //输入两个字符串
a[0]=str1.length(); //取得第一个字符串的长度
for(i=1;i<=a[0];i++) //把第一个字符串转换为整数,存放在数组a中
a[i]=str1[a[0]-i]-'0';
b[0]=str2.length(); //取得第二个字符串长度
for(i=1;i<=b[0];i++) //把第二个字符串中的每一位转换为整数,存放在数组B中
b[i]=str2[b[0]-i]-'0';
len=(a[0]>b[0]?a[0]:b[0]); //取两个字符串最大的长度
for(i=1;i<=len;i++) //做按位加法,同时处理进位
{
a[i]+=b[i];
a[i+1]+=a[i]/10;
a[i]%=10;
}
len++; //下面是去掉最高位的0,然后输出。
while((a[len]==0)&&(len>1)) len--;
for(i=len;i>=1;i--)
cout<<a[i];
return 0;
}
//注意:两个数相加,结果的位数,应该比两个数中大的那个数多一位。
Java Code:
import java.util.Scanner;
import java.math.*;
public class Main {
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
BigInteger a = cin.nextBigInteger();
BigInteger b = cin.nextBigInteger();
System.out.println(a.add(b));
}
}
Python Code:
a = int(input())
b = int(input())
print(a+b)