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符號表述
常用時間複雜度舉例
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