Loading [MathJax]/jax/output/HTML-CSS/fonts/TeX/fontdata.js

2015年3月7日 星期六

證明:連續分數取整之和的根號算法正確性

有一道經典問題是這樣子的:
「給予一個n,請計算nk=1nk

隨便寫一寫大概就會像這樣:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#include <bits/stdc++.h>

int main()
{
        int n,ans=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
                ans+=n/i;
        printf("%d\n",ans);
        return 0;
}

可惜這樣子的時間複雜度是O(n),實在太慢了。
可以發現這n項當中有許多項是一樣的,藉此加速便可達到O(n)
code長這樣子:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#include <bits/stdc++.h>

int main()
{
        int n,ans=0;
        scanf("%d",&n);
        for(int i=1;i<=n;)
        {
                int t=n/(n/i);
                ans+=(n/i)*(t-i+1);
                i=t+1;
        }
        printf("%d\n",ans);
        return 0; 
}



事實是:第9行那個動作可以精確的取到最大整數的t滿足nt=ni
而這篇的主旨便是要證明這件事。

證明分兩部份:

  • 證明nt=ni
  • 證明t為滿足該條件的上界,也就是證明nt+1ni


首先進行第一部份的證明。
n,m,kN+nk=m,試證nnm=m
nm就相當於程式碼中的tk相當於i
1.

nmnm

mnnm

m=mnnm



2.

m=nknk

mkn

k=knm

nknnm

m=nknnm



由1.、2.,得證nnm=m


接著進行第二部份的證明。
n,mN+,試證nnm+1m

nm<nm+1

nnm+1<m

nnm+1nnm+1<m

得證nnm+1m

沒有留言:

張貼留言