這題是十分經典的數學題,在其他各大oj也都有類似(相同)的題目
但是,我們還是從頭開始說
首先,這道題肯定不會是遞推,因為給出的f[1~6]就已經沒有遞推性了。。
所以,應該是一道模擬題(?)
演算法一:從1迴圈到n,每次列舉1~i的所有數,判斷是否為因數,ans++。。。
複雜度比O(n^2)小一些。。
程式碼如下:
#include<bits/stdc++.h>
using namespace std;
int n,ans;
int main(){
scanf("%d”,&n);
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++)
if(i%j==0) ans++;
printf("%d",ans);
return 0;
}
當然,會超時。。。
演算法二:利用小學數學知識(以及初中的根號),每次從1迴圈到n,列舉1~sqrt(n)(n的根號),
判斷i是否為因數,如果是,則必然有兩個因陣列成i,於是ans+=2。。。(這裡注意特判一下sqrt(n)的情況,這樣的情況ans只加一)
複雜度O(n*sqrt(n)),n<=10^6,最壞複雜度為10^9,會超時。。
程式碼如下
#include<bits/stdc++.h>
using namespace std;
long long n,ans;
int solve(int x){
int cnt=0;
for(int i=1;i<=sqrt(x);i++)
if(x%i==0){
cnt+=2;
if(i==sqrt(x)) cnt--;
}
return cnt;
}
int main(){
scanf("%lld",&n);
for(int i=1;i<=n;i++) ans+=solve(i);
printf("%lld",ans);
return 0;
}
演算法三:用篩法,但是不是正常的篩法:
因數的範圍是在1~n之間的,所以可以倒著考慮,一個數有幾個在1~n範圍內的倍數呢?
因此可以列舉每個1~n的因數,求出他有幾個倍數,然後ans加上倍數個數就行了(連根號都不用特判)。。
程式碼如下:
#include<bits/stdc++.h>
using namespace std;
int n,ans;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) ans+=n/i;
printf("%d",ans);
return 0;
}