1. 程式人生 > >中國大學MOOC-陳越、何欽銘-資料結構-起步能力自測題&程式碼

中國大學MOOC-陳越、何欽銘-資料結構-起步能力自測題&程式碼

題目網址

自測-1 列印沙漏(20 point(s))

本題要求你寫個程式把給定的符號列印成沙漏的形狀。例如給定17個“*”,要求按下列格式列印

這裡寫圖片描述

所謂“沙漏形狀”,是指每行輸出奇數個符號;各行符號中心對齊;相鄰兩行符號數差2;符號數先從大到小順序遞減到1,再從小到大順序遞增;首尾符號數相等。

給定任意N個符號,不一定能正好組成一個沙漏。要求打印出的沙漏能用掉儘可能多的符號。
輸入格式:

輸入在一行給出1個正整數N(≤1000)和一個符號,中間以空格分隔。
輸出格式:

首先打印出由給定符號組成的最大的沙漏形狀,最後在一行中輸出剩下沒用掉的符號數。

輸入樣例:

19 *

輸出樣例:

這裡寫圖片描述

思路:計算通項公式

程式碼如下:

#include <iostream>
#include <cstdio>
#include <cmath>

using namespace std;

int main()
{
    int x;//x表示輸入的值
    char c;//c表示所給定的符號
    cin>>x>>c;

    double n;
    int xx = x;
    n = sqrt((x + 1) / 2);//通項公式為1+2(3+5+7+...) = 2n^2-1 = x
    while(n != (int
)n) { xx--; n = sqrt((xx + 1) / 2); } int space = 0;//空格數 for(int i = 2 * n - 1; i >= 3; i-=2)//列印上半部分沙漏 { if(space) for(int j = 0; j < space; j++) printf(" "); for(int j = 0; j < i; j++) printf("%c", c); printf
("\n"); space++; } for(int j = 0; j < space; j++) printf(" "); printf("%c\n", c);//列印沙漏中間的1個符號 space--; for(int i = 3; i <= 2 * n - 1; i+=2)//列印下半個沙漏 { if(space) for(int j = 0; j < space; j++) printf(" "); for(int j = 0; j < i; j++) printf("%c", c); printf("\n"); space--; } int r = x - (2 * (int)n * (int)n - 1);//計算餘數 printf("%d", r); return 0; }

自測-2 素數對猜想(20 point(s))

讓我們定義d​n​​為:d​n​​=p​n+1​​−p​n​​,其中p​i​​是第i個素數。顯然有d​1​​=1,且對於n>1有d​n​​是偶數。“素數對猜想”認為“存在無窮多對相鄰且差為2的素數”。

現給定任意正整數N(<10​5​​),請計算不超過N的滿足猜想的素數對的個數。
輸入格式:

輸入在一行給出正整數N。
輸出格式:

在一行中輸出不超過N的滿足猜想的素數對的個數。

輸入樣例:

20

輸出樣例:

4

思路:使用快速素數篩選法篩出105內所有素數後計算素數對。
注:MAX的值應略大於最大給定N

程式碼如下:

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

#define MAX 100010

int prime[MAX], cnt;
bool num[MAX];

int main()
{
    //求10000以內的所有素數
    memset(num, 1, sizeof(num));
    num[0] = num[1] = 0;
    cnt = 1;
    for(int i = 2; i < MAX; i++)//快速素數篩法
    {
        if(num[i])
            prime[cnt++] = i;
        for(int j = 1; j < cnt && prime[j] * i < MAX; j++)//從2~MAX,用它們乘以比它們小的素數並篩去
            num[prime[j] * i] = 0;
    }

    //計算素數對
    int n, c = 0;
    cin>>n;
    for(int i = 2; prime[i] <= n; i++)
    {
        if(prime[i] - prime[i - 1] == 2)
            c++;
    }
    cout<<c<<endl;
    return 0;
}

自測-3 陣列元素迴圈右移問題(20 point(s))

一個數組A中存有N(>0)個整數,在不允許使用另外陣列的前提下,將每個整數迴圈向右移M(≥0)個位置,即將A中的資料由(A​0​​A​1​​⋯A​N−1​​)變換為(A​N−M​​⋯A​N−1​​A​0​​A​1​​⋯A​N−M−1​​)(最後M個數迴圈移至最前面的M個位置)。如果需要考慮程式移動資料的次數儘量少,要如何設計移動的方法?
輸入格式:

每個輸入包含一個測試用例,第1行輸入N(1≤N≤100)和M(≥0);第2行輸入N個整數,之間用空格分隔。
輸出格式:

在一行中輸出迴圈右移M位以後的整數序列,之間用空格分隔,序列結尾不能有多餘空格。

輸入樣例:

6 2
1 2 3 4 5 6

輸出樣例:

5 6 1 2 3 4

:emmm……偷了點懶沒有按照題目要求模擬……

程式碼如下:

#include <iostream>

using namespace std;

int num[105];

int main()
{
    int n, m;
    cin>>n>>m;
    for(int i = 0; i < n; i++)
        cin>>num[i];

    int r = m % n;

    for(int i = n - r; i < n; i++)
        cout<<num[i]<<" ";

    for(int i = 0; i < n - r; i++)
    {
        cout<<num[i];
        if(i != n - r - 1)
            cout<<" ";
    }

    cout<<endl;

    return 0;
}

自測-4 Have Fun with Numbers(20 point(s))

Notice that the number 123456789 is a 9-digit number consisting exactly the numbers from 1 to 9, with no duplication. Double it we will obtain 246913578, which happens to be another 9-digit number consisting exactly the numbers from 1 to 9, only in a different permutation. Check to see the result if we double it again!

Now you are suppose to check if there are more numbers with this property. That is, double a given number with k digits, you are to tell if the resulting number consists of only a permutation of the digits in the original number.
Input Specification:

Each input contains one test case. Each case contains one positive integer with no more than 20 digits.
Output Specification:

For each test case, first print in a line “Yes” if doubling the input number gives a number that consists of only a permutation of the digits in the original number, or “No” if not. Then in the next line, print the doubled number.
Sample Input:

1234567899

Sample Output:

Yes
2469135798

題目大意:輸入一個數字,乘以2, 看輸入的數字和乘2後的結果出現的數字是否相同。比如輸入中出現了123456789,乘2後的結果為246913578,也出現了123456789.

unsigned int 0~4294967295
int 2147483648~2147483647
unsigned long 0~4294967295
long 2147483648~2147483647
long long的最大值:9223372036854775807
long long的最小值:-9223372036854775808
unsigned long long的最大值:1844674407370955161
__int64的最大值:9223372036854775807
__int64的最小值:-9223372036854775808
unsigned __int64的最大值:18446744073709551615

思路:因為輸入的資料最大不超過20位,所以即使使用unsigned __int64也會超,只能手動寫*2的程式碼,輸入和結果儲存在兩個陣列中,排序後比較。

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

char num[25];//方便輸入
int num1[25], num2[25];//模擬計算用的原陣列和兩倍陣列
int n[25];//用來儲存*2後的結果

int main()
{
    cin>>num;

    int carry = 0;//進位
    int len = strlen(num);
    for(int i = len - 1; i >= 0; i--)
    {
        num1[i] = num[i] - '0';
        num2[i] = (num1[i] *2) % 10;
        if(carry)
        {
            num2[i]++;
            carry = 0;
        }
        if((num1[i] * 2) / 10)
            carry = 1;
        n[i] = num2[i];
    }

    if(carry)//若最高位有1則一定不相等,故不用比較。但注意輸出最高位的1
        cout<<"No"<<endl<<"1";
    else//排序後比較兩個陣列
    {
        sort(num1, num1 + len);
        sort(num2, num2 + len);

        bool flag = true;
        for(int i = 0; i < len; i ++)
        {
          if(num1[i] != num2[i])
            {
                flag = false;
                cout<<"No"<<endl;
                break;
            }
        }
        if(flag)
            cout<<"Yes"<<endl;
    }
    for(int i = 0; i < len; i++)
        cout<<n[i];
    return 0;
}

自測-5 Shuffling Machine(20 point(s))

Shuffling is a procedure used to randomize a deck of playing cards. Because standard shuffling techniques are seen as weak, and in order to avoid “inside jobs” where employees collaborate with gamblers by performing inadequate shuffles, many casinos employ automatic shuffling machines. Your task is to simulate a shuffling machine.

The machine shuffles a deck of 54 cards according to a given random order and repeats for a given number of times. It is assumed that the initial status of a card deck is in the following order:

S1, S2, …, S13,
H1, H2, …, H13,
C1, C2, …, C13,
D1, D2, …, D13,
J1, J2

where “S” stands for “Spade”, “H” for “Heart”, “C” for “Club”, “D” for “Diamond”, and “J” for “Joker”. A given order is a permutation of distinct integers in [1, 54]. If the number at the i-th position is j, it means to move the card from position i to position j. For example, suppose we only have 5 cards: S3, H5, C1, D13 and J2. Given a shuffling order {4, 2, 5, 3, 1}, the result will be: J2, H5, D13, S3, C1. If we are to repeat the shuffling again, the result will be: C1, H5, S3, J2, D13.
Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer K (≤20) which is the number of repeat times. Then the next line contains the given order. All the numbers in a line are separated by a space.
Output Specification:

For each test case, print the shuffling results in one line. All the cards are separated by a space, and there must be no extra space at the end of the line.
Sample Input:

2
36 52 37 38 3 39 40 53 54 41 11 12 13 42 43 44 2 4 23 24 25 26 27 6 7 8 48 49 50 51 9 10 14 15 16 5 17 18 19 1 20 21 22 28 29 30 31 32 33 34 35 45 46 47

Sample Output:

S7 C11 C10 C12 S1 H7 H8 H9 D8 D9 S11 S12 S13 D10 D11 D12 S3 S4 S6 S10 H1 H2 C13 D2 D3 D4 H6 H3 D13 J1 J2 C1 C2 C3 C4 D1 S5 H5 H11 H12 C6 C7 C8 C9 S2 S8 S9 H10 D5 D6 D7 H4 H13 C5

題目大意:根據輸入的陣列洗54張牌,比如樣例中將第一張牌移到第36這個位置、第二張牌移到第52個位置、第三張牌移動到第37個位置……
輸入的第一個數字表示按照這個陣列洗牌的次數

思路:打表,模擬

#include <iostream>
#include <cstring>

using namespace std;

string s[25][60] = {"S1", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9", "S10", "S11", "S12", "S13", "H1", "H2", "H3", "H4", "H5", "H6", "H7", "H8", "H9", "H10", "H11", "H12", "H13", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "C10", "C11", "C12", "C13", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "D10", "D11", "D12", "D13", "J1", "J2"};
int num[60];

int main()
{
    int n, cnt = 0;
    cin>>n;
    for(int i = 0; i < 54; i++)
        cin>>num[i];
    while(n--)
    {
        for(int i = 0; i < 54; i++)
            s[cnt + 1][num[i] - 1] = s[cnt][i];
        cnt++;
    }
    for(int i = 0; i < 53; i++)
        cout<<s[cnt][i]<<" ";
    cout<<s[cnt][53];
    return 0;
}