1. 程式人生 > >網易2018春招筆試程式設計題——nk數對

網易2018春招筆試程式設計題——nk數對

題目描述:

牛牛以前在老師那裡得到了一個正整數數對(x, y), 牛牛忘記他們具體是多少了。

但是牛牛記得老師告訴過他x和y均不大於n, 並且x除以y的餘數大於等於k。

牛牛希望你能幫他計算一共有多少個可能的數對。

首先用兩個for迴圈來暴力求解是可以得到結果,但是時間複雜度太高。所以需要從數學的角度分析,尋找新的思路。

1.首先分析數對的右邊的數。x%y的餘數,其餘數的範圍必定為[0—y-1],所以為了滿足餘數大於等於k,這個y必須為k+1或者更大,x%y的餘數才可能出現k。

2.題目明確為正整數數對,分析x%y與其餘數的關係。可以其餘數是迴圈出現的。

對於一個b, n範圍內的數模b的序列應該是:


0,1,2,...,b-1, 0, 1, 2,..., b-1,...0,1,2,..n%b

比如b為3,n為1-10.

由這個例子,我們可以看出來,1,2,0迴圈出現,完整出現的迴圈有3次,剩下可能有一次不完整的迴圈。

可知,完整迴圈次數為3/10,不完整迴圈的長度為3%10,不管是哪種,都是從1開始的。

#include <bits/stdc++.h>
 
using namespace std;
 
int main() {
    int n, k;
    cin >> n >> k;
    if(k == 0) cout << 1LL * n * n << endl;
    else {
        long long ans = 0;
        for(int i = k + 1; i <= n; i++){
            ans += (n / i) * (i - k);
            if(n % i >= k)    ans += n % i - k + 1;
        }
        cout << ans << endl;
    }
    return 0;
}

程式分析:

1.for 迴圈中i變數就是數對的右邊的數

2.對於數對的右邊的數為i的這些數對,只需要分析兩種情況,完整迴圈和不完整迴圈

3.分析完整迴圈:迴圈次數為n/i。因為[0—i-1]是餘數的範圍(但實際出現順序為0在結尾),也是迴圈的範圍,排除前k個數(想象從0開始排除),那麼剩下的餘數肯定是大於等於k的。

4.分析不完整迴圈:只有一次,但長度不定。長度為n%i。分析上面的例子,發現其餘數範圍為[1,2,3,,,,n%i],也是實際出現順序。所以排除前k-1個數(和上面不同的是,這裡是從1開始的,所以只需要排除k-1個數),那麼剩下的餘數都是大於等於k的。所以if的判斷條件為n%i>=k,因為這樣剛好最後一個餘數為k。