2018级《算法分析与设计》练习6

2018级《算法分析与设计》练习6(java)

  • 问题 C: 与7相关的数
  • 问题 B: 鸡兔共笼
  • 问题 C: 买房
  • 问题 D: 棋盘覆盖问题
  • 问题 E: 大整数乘法
  • 问题 F: 第k小元素问题
  • 问题 G: 找中位数
  • 问题 H: 矩阵乘法
  • 问题 I: Matrix multiplication
  • 问题 J: 机器人的指令

问题 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
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
#include 
#include
 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
#include
#include
#include
#include
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 
#include 
#include 
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;
}

你可能感兴趣的:(算法题)