2018級《算法分析與設計》練習6(java)
問題 C: 與7相關的數
題目描述
一個正整數,如果它能被7整除,或者它的十進制表示法中某個位數上的數字爲7, 則稱其爲與7相關的數。
現求所有小於等於n(n<100)的與7無關的正整數的平方和。
輸入
案例可能有多組。對於每個測試案例輸入爲一行,正整數n,(n<100)。
輸出
對於每個測試案例輸出一行,輸出小於等於n的與7無關的正整數的平方和。
樣例輸入 Copy
21
樣例輸出 Copy
2336
import java.util.Scanner;
public class Main {
public static boolean isIn7(int a) {
if(a%7==0) {return true;}
int temp=a;
while(temp>0){
if(temp%10==7){
return true;
}
temp /=10;
}
return false;
}//判斷是否包含7
public static void main(String[] args) {
//一個正整數,如果它能被7整除,或者它的十進制表示法中某個位數上的數字爲7, 則稱其爲與7相關的數。
// 現求所有小於等於n(n<100)的與7無關的正整數的平方和。
Scanner cin=new Scanner(System.in);
while(cin.hasNext()) {
int n=cin.nextInt();
int sum=0;
for(int i=1;i<=n;i++) {
if(!isIn7(i)) {
sum+=i*i;
}
}
System.out.println(sum);
}
}
}
問題 B: 雞兔共籠
題目描述
一個籠子裏面關了雞和兔子(雞有2只腳,兔子有4只腳,沒有例外)。
已經知道了籠子裏面腳的總數a,問籠子裏面至少有多少隻動物,至多有多少隻動物。
輸入
每組測試數據佔1行,每行一個正整數a (a < 32768)。
輸出
輸出包含n行,每行對應一個輸入,包含兩個正整數,第一個是最少的動物數,第二個是最多的動物數,兩個正整數用一個空格分開。
如果沒有滿足要求的答案,則輸出兩個0。
樣例輸入 Copy
2
3
20
樣例輸出 Copy
0 0
5 10
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner cin=new Scanner(System.in);
int n=cin.nextInt();
while(n>0) {
int m=cin.nextInt();
if(m%2!=0) {
System.out.print(0);
System.out.print(" ");
System.out.println(0);
}else {
int min,max;
int q,r,e;
int canyu,canyu2;
q=m/2;
canyu=m%2/4;
max=q+canyu;
e=m/4;
canyu2=m%4/2;
min=canyu2+e;
System.out.print(min);
System.out.print(" ");
System.out.println(max);
}
n--;
}
}
}
問題 C: 買房
題目描述
某程序員開始工作,年薪N萬,他希望在中關村公館買一套60平米的房子,現在價格是200萬。
假設房子價格以每年百分之K增長,並且該程序員未來年薪不變,且不吃不喝,不用交稅。
每年所得N萬全都積攢起來,問第幾年能夠買下這套房子(第一年房價200萬,收入N萬)。
輸入
有多行,每行兩個整數N(10<=N<=50), K(1<=K<=20)。
輸出
針對每組數據,如果在第21年或者之前就能買下這套房子,則輸出一個整數M,表示最早需要在第M年能買下,否則輸出Impossible,輸出需要換行。
樣例輸入 Copy
50 10
40 10
40 8
樣例輸出 Copy
8
Impossible
10
#include<iostream>
using namespace std;
int main()
{
double n;
double k;
while(cin>>n>>k)
{
double y=1;
double M=200;
double All=n;
while(true)
{
All+=n;
M*=(1+k/100);
if(All>M)
{
cout<<y+1<<endl;
break;
}
if(y>20)
{
cout<<"Impossible"<<endl;
break;
}
y++;
}
}
return 0;
}
問題 D: 棋盤覆蓋問題
題目描述
在一個n×n (n = 2k)個方格組成的棋盤中,恰有一個方格與其他方格不同,稱該方格爲一特殊方格,且稱該棋盤爲一特殊棋盤。
在棋盤覆蓋問題中,要用圖示的4種不同形態的L型骨牌覆蓋給定的特殊棋盤上除特殊方格以外的所有方格,且任何2個L型骨牌不得重疊覆蓋。
輸入
多組測試用例,每組測試用例包括兩部分,
第一部分爲方格的寬度n,
第二部分則爲方格,特殊方格爲-1,其他方格爲0。
輸出
輸出覆蓋後的方案
樣例輸入 Copy
4
-1 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
樣例輸出 Copy
-1 2 4 4
2 2 1 4
3 1 1 5
3 3 5 5
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
//tr表示棋盤左上角行號
//tc表示棋盤左上角列號
//dr表示特殊棋盤的行號
//dc表示特殊棋盤的列號
//size = 2^k
//棋盤的規格爲2^k * 2^k
int tile=1;
static int board[8][8];
void chessBoard(int tr, int tc, int dr, int dc, int size) {
if (size == 1) return;
int t = tile++, // L型骨牌號
s = size/2; // 分割棋盤
// 覆蓋左上角小棋盤
if (dr < tr + s && dc < tc + s)
// 特殊方格在此棋盤中
chessBoard(tr, tc, dr, dc, s);
else {// 此棋盤中無特殊方格
// 用 t 號L型骨牌覆蓋右下角
board[tr + s - 1][tc + s - 1] = t;
// 覆蓋其餘方格
chessBoard(tr, tc, tr+s-1, tc+s-1, s);}
// 覆蓋左下角小棋盤
if (dr >= tr + s && dc < tc + s)
// 特殊方格在此棋盤中
chessBoard(tr+s, tc, dr, dc, s);
else {// 用 t 號L型骨牌覆蓋右上角
board[tr + s][tc + s - 1] = t;
// 覆蓋其餘方格
chessBoard(tr+s, tc, tr+s, tc+s-1, s);}
// 覆蓋右上角小棋盤
if (dr < tr + s && dc >= tc + s)
// 特殊方格在此棋盤中
chessBoard(tr, tc+s, dr, dc, s);
else {// 此棋盤中無特殊方格
// 用 t 號L型骨牌覆蓋左下角
board[tr + s - 1][tc + s] = t;
// 覆蓋其餘方格
chessBoard(tr, tc+s, tr+s-1, tc+s, s);}
// 覆蓋右下角小棋盤
if (dr >= tr + s && dc >= tc + s)
// 特殊方格在此棋盤中
chessBoard(tr+s, tc+s, dr, dc, s);
else {// 用 t 號L型骨牌覆蓋左上角
board[tr + s][tc + s] = t;
// 覆蓋其餘方格
chessBoard(tr+s, tc+s, tr+s, tc+s, s);}
}
int main()
{ int i,j;
int x,y;
int n;
while(scanf("%d",&n)!=EOF){
for(i=0;i<n;i++){
for(j=0;j<n;j++){
scanf("%d",&board[i][j]);
}
}
//尋找特殊點座標
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if(board[i][j]==-1){
x=i;
y=j;
}
}
}
chessBoard(0,0,x,y,n);
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
cout<<board[i][j]<<" ";
}
cout<<endl;
}
//初始化
tile=1;
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
board[i][j]=0;
}
}
}
return 0;
}
問題 E: 大整數乘法
題目描述
使用分治算法實現兩個大整數相乘。
輸入
兩個十進制大整數,滿足每一個整數長度爲2^n且兩個大整數的長度相等。(多組數據)
輸出
兩個大整數的乘積。
樣例輸入 Copy
1234 5678
樣例輸出 Copy
7006652
#include<stdio.h>
#include<stdbool.h>
#include<math.h>
int sign(long value){
return value>0?1:-1;
}
long solve(long x,long y,int n){
int s=sign(x)*sign(y);//判斷符號
x=abs(x);
y=abs(y);
if(x==0||y==0){
return 0;
}
else if(n==1){
return s*x*y;}
else{
long A=(long)(x/pow(10,n/2));
long B=(x%(long)pow(10,n/2));
long C=(long)(y/pow(10,n/2));
long D=(y%(long)pow(10,n/2));
long AC=solve(A,C,n/2);
long BD=solve(B,D,n/2);
long ABCD=solve((A-B),(D-C),n/2)+AC+BD;
return (long)(s*(AC*pow(10,n)+ABCD*pow(10,n/2)+BD));
}
}
int len(int n){
int count=0;
while(n != 0)
{
// n = n/10
n /= 10;
++count;
}
return count;
}//計算位數
int main(){
long n,m;
while(scanf("%d%d",&n,&m)!=EOF){
int leng=len(n);
printf("%d\n",solve(n,m,leng)); }
}
問題 F: 第k小元素問題
題目描述
輸入一個整數數組,請求出該數組的第k小元素。要求時間複雜度爲O(n)。
輸入
每組輸入包括兩行,第一行爲一個整數數組,兩個數字之間用空格隔開;第二行爲k值。數組中元素個數小於10^9。
輸出
輸出第k小元素的值。
樣例輸入 Copy
2 5 6 1 8 7 9
2
樣例輸出 Copy
2
#include<iostream>
#include<cstdio>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
vector<int>v;
int i,j;
int main(){
int y;
int lenght;
while(~scanf("%d",&y)){
v.push_back(y);
int x;
while(scanf("%d",&x)){
v.push_back(x);
if(getchar()=='\n')
break;
}
sort(v.begin(),v.end());
int k;
scanf("%d",&k);
printf("%d\n",v[k-1]);
v.clear();//清空vector
}
}
問題 G: 找中位數
題目描述
請設計一個算法,不排序,快速計算出一個無序數列的中位數。 時間複雜度要求爲O(n)。
如果有奇數個元素,中位數則是數組排序後最中間的那個數字。
如果是偶數個元素,中位數則是數組排序後最中間兩個元素的平均值。
輸入
有多組輸入,每組輸入的第一行爲n(1<=n<=1e5),表示該數列的元素個數。
第二行爲n個整數組成的無序數列
輸出
每組樣例輸出一行,表示該無序數列的中位數。
若爲偶數,請保留三位小數
若爲奇數,直接輸出
樣例輸入 Copy
5
5 3 2 1 4
樣例輸出 Copy
3
import java.text.DecimalFormat;
import java.util.Scanner;
public class Main {
public static void swap(int a[],int p,int q) {
int t;
t=a[p];
a[p]=a[q];
a[q]=t;
}
public static int partition(int a[],int p,int q) {
int x=a[p];
int i=p,j;
for(j=p+1;j<=q;j++) {
if(a[j]<x) {
i++;
swap(a,i,j);
}
}
swap(a,p,i);
return i;
}
public static void getMid(int a[],int p,int q) {
int mid=(p+q)/2;
while(true) {
int pos=partition(a,p,q);
if(pos==mid)break;
else if(pos>mid) {q=pos-1;}
else {p=pos+1;}
}
if(a.length%2!=0) {
System.out.println(a[mid]);}
else {
double MID=1.0*(a[mid]+a[mid+1])/2;
System.out.println(String.format("%.3f", MID));
}
}
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
while(cin.hasNext()) {
int n=cin.nextInt();
int a[]=new int[n];
for(int i=0;i<a.length;i++) {
a[i]=cin.nextInt();
}
getMid(a,0,a.length-1);
}
}
}
問題 H: 矩陣乘法
題目描述
設M1和M2是兩個n×n的矩陣,使用分治法計算M1×M2 的乘積。n爲2^k,且k<=10。
輸入
一個整數n表示矩陣的維數,接下來n行爲第一個矩陣,再下面n行爲第二個矩陣。
輸出
矩陣的乘積(兩個數字之間空一格,數字右對齊)。
樣例輸入 Copy
2
1 1
2 2
3 3
4 4
樣例輸出 Copy
7 7
14 14
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
int n=cin.nextInt();
int[][] Matrix1=new int[n+1][n+1] ;
int[][] Matrix2=new int[n+1][n+1];
int [][] ans=new int[n+1][n+1];
DecimalFormat df=new DecimalFormat("-");
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) {
Matrix1[i][j]=cin.nextInt();
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) {
Matrix2[i][j]=cin.nextInt();
}
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++) {
for(int k=1;k<=n;k++) {
ans[i][j]+=Matrix1[i][k]*Matrix2[k][j];
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++) {
System.out.printf("%2d",ans[i][j]);
System.out.print(" ");
}
System.out.println();
}
}
}
問題 I: Matrix multiplication
題目描述
Given two matrices A and B of size n×n, find the product of them.
bobo hates big integers. So you are only asked to find the result modulo 3.
輸入
The input consists of several tests. For each tests:
The first line contains n (1≤n≤800). Each of the following n lines contain n integers – the description of the matrix A. The j-th integer in the i-th line equals Aij. The next n lines describe the matrix B in similar format (0≤Aij,Bij≤109).
輸出
For each tests:
Print n lines. Each of them contain n integers – the matrix A×B in similar format.
樣例輸入 Copy
1
0
1
2
0 1
2 3
4 5
6 7
樣例輸出 Copy
0
0 1
2 1
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);
int n=cin.nextInt();
int[][] Matrix1=new int[n+1][n+1] ;
int[][] Matrix2=new int[n+1][n+1];
int [][] ans=new int[n+1][n+1];
DecimalFormat df=new DecimalFormat("-");
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) {
Matrix1[i][j]=cin.nextInt();
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) {
Matrix2[i][j]=cin.nextInt();
}
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++) {
for(int k=1;k<=n;k++) {
ans[i][j]+=Matrix1[i][k]*Matrix2[k][j];
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++) {
System.out.printf("%2d",ans[i][j]);
System.out.print(" ");
}
System.out.println();
}
}
}
問題 J: 機器人的指令
題目描述
數軸原點有一個機器人。該機器人將執行一系列指令,你的任務是預測所有指令執行完畢之後它的位置。
LEFT:往左移動一個單位
RIGHT: 往右移動一個單位
SAME AS i: 和第i條執行相同的動作。輸入保證i是一個正整數,且不超過之前執行指令數
輸入
輸入第一行爲數據組數T (T<=100)。每組數據第一行爲整數n (1<=n<=100),即指令條數。以下每行一條指令。指令按照輸入順序編號爲1~n。
輸出
對於每組數據,輸出機器人的最終位置。每處理完一組數據,機器人應復位到數軸原點。
樣例輸入 Copy
2
3
LEFT
RIGHT
SAME AS 2
5
LEFT
SAME AS 1
SAME AS 2
SAME AS 1
SAME AS 4
樣例輸出 Copy
1
-5
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
char s[10],c[10];
int a[100];
int main()
{
int T,n,m;
scanf("%d",&T);
while(T--)
{
int sum=0;
memset(a,0,sizeof(a));
scanf("%d",&n);
for(int i=0;i<n;i++)
{
cin>> s;
if(s[0]=='L')
a[i]--;
if(s[0]=='R')
a[i]++;
if(s[0]=='S')
{
cin>>c; //AS
cin>>m;//數字
a[i]=a[m-1];//找到前面的數組m-1的值
}
}
for(int i=0;i<n;i++)
sum+=a[i];
printf("%d\n",sum);
}
return 0;
}