2022 CSP-J 閱讀程式3

随手一只风發表於2024-09-12

1 2022 CSP-J 閱讀程式3

閱讀程式(程式輸入不超過陣列或字串定義的範圍;判斷題正確填 √,錯誤填×;除特 殊說明外,判斷題 1.5 分,選擇題 3 分)

原始碼

#include<iostream>
 
using namespace std;

int n,k;

int solve1()
{
    int l=0,r=n;
    while(l<=r){
        int mid=(l+r)/2;
        if(mid * mid <=n) l=mid+1;
        else r=mid-1;
    }
    return l-1;
}

double solve2(double  x)
{
    if(x == 0) return x;
    for(int i=0;i<k;i++)
        x=(x+n/x)/2;
    return x;
}

int main()
{
    cin>>n>>k;
    double ans=solve2(solve1());
    cout<<ans<<' '<<(ans * ans == n)<<endl;
    return 0;
}

假設int為32位有符號整數型別,輸入的n是不超過47000的自然數、k是不超過int表示範圍的自然數,完成下面的判斷題和單選題

判斷題

28.該演算法最準確的時間複雜度分析結果為O(logn+k) ( )

29.當輸入為"9801 1"時,輸出的第一個數為"99" 。( )

30.對於任意輸入的n,隨著所輸入k的增大,輸出的第2個數會變成"1" 。( )

31.該程式有存在缺陷。當輸入的n過大時,第12行的乘法有可能溢位,因此應當將mid強制轉換為64位整數再計算。( )

單選題

32.當輸入為 “2 1” 時,輸出的第一個數最接近( )

A. 1

B. 1.414

C. 1.5

D. 2

33.當輸入"3 10"時,輸出的第一個數最接近( )

A. 1.7

B. 1.732

C. 1.75

D. 2

34.當輸入為"256 11"時,輸出的第一個數( )

A. 等於16

B. 接近但小於16

C. 接近但大於16

D. 前三種情況都有可能

2 相關知識點

1) 演算法時間複雜度

演算法時間複雜度定性描述該演算法的執行時間,常用大O符號表述

常用時間複雜度舉例

2022 CSP-J 閱讀程式3

2) 二分答案

二分答案顧名思義,它用二分的方法列舉答案,並且列舉時判斷這個答案是否可行

直接對答案進行列舉查詢,接著判斷答案是否合法。如果合法,就將答案二分進一步靠近,如果不合法,就接著二分縮小判斷。這樣就可以大大的減少時間。

二分中有時可以得可行得答案,但不是最大的,繼續向右靠近,求出最大值

示例

 int ans = 1;
 int l = 1,r = 100000;//在1~100000之間的整數列舉 
 while(l <= r){
     int m = l + (r - l) / 2;
     if(check(m)){//滿足 則進行向右縮小範圍 看看有沒有更大的 
         ans = m;//可能多次賦值 最後一定是可能的最大值 
         l = m + 1;
      }else{//不滿足縮小邊長 向左縮小範圍 用更小邊長繼續嘗試 
         r = m - 1;
	  } 
  }

二分查詢時間複雜度分析

二分查詢每次都縮小或擴大為原來的一半和上面示例4類似,所以也是Olog(n)

3 思路分析

solve1函式

int solve1()
{
    int l=0,r=n;
    while(l<=r){
        int mid=(l+r)/2;
        if(mid * mid <=n) l=mid+1;
        else r=mid-1;
    }
    return l-1;
}

solve1函式是一個標準的二分答案演算法,找到1個數x ,使得x * x 無限接近於n

也就是求n的平方根,當n=4時進行驗證

n=4  l=0 r=4
//0<=4 進入迴圈
//第1次迴圈
mid=(l+r)/2=(0+4)/2=2 ,mid * mid =2 * 2=4<=4 條件滿足 l=mid+1=2+1=3 r=4
//3<=4 條件滿足
//第2次迴圈
mid=(l+r)/2=(3+4)/2=3, mid * mid =3 * 3 =9<=4 不滿足,r=mid-1=3-1=2 l=3
//3<=2 條件不滿足 退出迴圈
//返回 l-1 = 3 -1 =2
//所以當n=4時,函式solve1返回2,是4得平方根

如果n=5,是否也可以算出其平方根呢?

n=5  l=0 r=5
//0<=5 進入迴圈
//第1次迴圈
mid=(l+r)/2=(0+5)/2=2 ,mid * mid =2 * 2=4<=5 條件滿足 l=mid+1=2+1=3 r=5
//3<=5 條件滿足
//第2次迴圈
mid=(l+r)/2=(3+5)/2=4, mid * mid =4 * 4 =16<=5 不滿足,r=mid-1=4-1=3 l=3
//3<=3 條件滿足
//第3次迴圈
mid=(l+r)/2=(3+3)/2=3, mid * mid =3 * 3 =9<=5 不滿足,r=mid-1=3-1=2 l=3
//3<=2 條件不滿足 退出迴圈
//返回 l-1 = 3 -1 =2
//所以當n=5時,函式solve1返回2,不是5得平方根,2是小於5平方根得最大整數

根據如下程式碼,可以大概猜測solve2是輔助求出平方根是小數的情況,如果猜不出,可以模擬對應資料

double ans=solve2(solve1());
cout<<ans<<' '<<(ans * ans == n)<<endl;

假設int為32位有符號整數型別,輸入的n是不超過47000的自然數、k是不超過int表示範圍的自然數,完成下面的判斷題和單選題

判斷題

28.該演算法最準確的時間複雜度分析結果為O(logn+k) ( T )

分析

此題呼叫了2次函式,solve1和solve2,其中solve1是二分答案,時間複雜度為O(logn),solve2的時間複雜度為O(k)

所以準確的時間複雜度為2者之和O(logn+k)

29.當輸入為"9801 1"時,輸出的第一個數為"99" 。( T )

分析

n=9801 ,求其對應平方根是99

k為1,執行1次 x = (x + n / x) / 2;

x=(99 + 9801/99)/2=99

所以是99

30.對於任意輸入的n,隨著所輸入k的增大,輸出的第2個數會變成"1" 。( F )

分析

如果平方根不是整數,求出結果沒有精確的值,只能計算n的近似值,所以不會相等,返回false為0

31.該程式有存在缺陷。當輸入的n過大時,第12行的乘法有可能溢位,因此應當將mid強制轉換為64位整數再計算。( F )

分析

n最大是47000,中間可能導致溢位的是mid * mid,最大是(47000/2)*(47000/2)不會超過int的表示範圍21億

單選題

32.當輸入為 “2 1” 時,輸出的第一個數最接近( C )

A. 1

B. 1.414

C. 1.5

D. 2

分析

當n=2時,solve1求出平方根整數為1

//模擬過程
n=2  l=0 r=2
//0<=2 進入迴圈
//第1次迴圈
mid=(l+r)/2=(0+2)/2=1 ,mid * mid =1 * 1=1<=2 條件滿足 l=mid+1=1+1=2 r=2
//2<=2 條件滿足
//第2次迴圈
mid=(l+r)/2=(2+2)/2=2, mid * mid =2 * 2 =4<=2 不滿足,r=mid-1=2-1=1 l=2
//2<=1 條件不滿足 退出迴圈
//返回 l-1 = 2 -1 =1

k為1,執行1次 x = (x + n / x) / 2;

x=(1+2/1)/2=1.5

所以選C

33.當輸入"3 10"時,輸出的第一個數最接近( B )

A. 1.7

B. 1.732

C. 1.75

D. 2

分析

當n=3時,solve1求出平方根整數為1

//模擬過程
n=3  l=0 r=3
//0<=3 進入迴圈
//第1次迴圈
mid=(l+r)/2=(0+3)/2=1 ,mid * mid =1 * 1=1<=3 條件滿足 l=mid+1=1+1=2 r=3
//2<=3 條件滿足
//第2次迴圈
mid=(l+r)/2=(2+3)/2=2, mid * mid =2 * 2 =4<=3 不滿足,r=mid-1=2-1=1 l=2
//2<=1 條件不滿足 退出迴圈
//返回 l-1 = 2 -1 =1

k為10,執行10次 x = (x + n / x) / 2;

第1次 x=(1+3/1)/2=2
第2次 x=(2+3/2)/2=1.75
第3次 x=(1.75+3/1.75)/2=1.732
第4次 x=(1.732+3/1.732)/2=1.732
3/1.732 =1.732 所以後續計算約等於1.732

所以選B

34.當輸入為"256 11"時,輸出的第一個數( A )

A. 等於16

B. 接近但小於16

C. 接近但大於16

D. 前三種情況都有可能

分析

當n=256時,solve1求出平方根整數為16

//模擬過程
n=256  l=0 r=256
//0<=256 進入迴圈
//第1次迴圈
mid=(l+r)/2=(0+256)/2=128 ,mid * mid =128 * 128<=256 條件不滿足 r=mid-1=128-1=127 l=0
//0<=127 條件滿足
//第2次迴圈
mid=(l+r)/2=(0+127)/2=63, mid * mid =63 * 63 <=256 條件不滿足,r=mid-1=63-1=62 l=0
//0<=62 條件滿足
//第3次迴圈
mid=(l+r)/2=(0+62)/2=31, mid * mid =31 * 31 <=256 條件不滿足,r=mid-1=31-1=30 l=0 
//0<=30 條件滿足
//第4次迴圈
mid=(l+r)/2=(0+30)/2=15, mid * mid =15 * 15 =225 <=256 條件滿足,l=mid+1=15+1=16 r=30    
//16<=30 條件滿足
//第5次迴圈
mid=(l+r)/2=(16+30)/2=24, mid * mid =24 * 24<=256 不滿足,r=mid-1=24-1=2 l=16
//16<=23 條件滿足
//第6次迴圈
mid=(l+r)/2=(16+23)/2=19, mid * mid =19 * 19<=256 不滿足,r=mid-1=19-1=18 l=16
//16<=18條件滿足
//第7次迴圈
mid=(l+r)/2=(16+18)/2=17, mid * mid =17 * 17<=256 不滿足,r=mid-1=17-1=16 l=16
//16<=16條件滿足
//第8次迴圈
mid=(l+r)/2=(16+16)/2=16, mid * mid =16 * 16<=256 條件滿足,l=mid+1=16+1=17 r=16     
//17<=16 條件不滿足 退出迴圈
//返回 l-1 = 17 -1 =16

k為11,執行11次 x = (x + n / x) / 2;

第1次 x=(16+256/16)/2=16
第2次 x=(16+256/16)/2=16
....
第11次 x=(16+256/16)/2=16

所以選A

相關文章