【題目描述】
q次詢問,每次給一個x,問1到x的因數個數的和。1<=q<=10 ,1<= x <=10^9
【輸入描述】
第一行一個正整數q, 接下來q行,每行一個正整數 x
【輸出描述】
共q行, 每行一個正整數表示答案
【示例】
【輸入】
4
1
2
3
10
【輸出】
1
3
5
27
【思路分析】
方法1:最簡單的就是把1~x各個數的因數個數都求出來再求和。
不過這樣做顯然會超時。
方法2:換一種思路考慮,從1~x 這x個數,每個數都會有1這個因數,每2個數會有一個因數2,每3個數會有一個因數3,.......
所以,1~x 共有 x/1 個因數1,x/2個因數2,x/3個因數3,……,x/n個因數n(1<=n<=x),所以最終個數和爲
再寫代碼就比較簡單了,這裏就不贅述了。但還能不能把計算時間再縮小下呢,或者說有沒有計算量更小的方法呢?
方法3:假設n爲x的因數,那麼x/n 也一定爲x的因數,假設sq爲x的算術平方根,那麼x的因數可以分爲兩部分,一部分都小於sq,一部分都大於(等於)sq。基於方法2,我們也就只需要計算的數值,然後再乘以2。於是我們興致勃勃的去寫代碼了,但是發現程序跑出來的結果並不正確。比之前多了許多。略作研究,我們發現,若x = 1,4,9,16等等,n=1,2,3,4等,n是x的因數,x/n的值正好也是n,我們盲目的乘以2,多計算了sq個。於是我們把代碼修正一下,減去這sq個數字,發現還是多着許多。再仔細看一下不難發現,對於小於sq的因數,每個因數我們都多計算了sq個。綜合前面等於sq的情況,也就是多計算了sq個sq(sq*sq)。這樣說可能比較抽象,舉個例子說一下:
假設x=16,於是,我們求1~16的因數個數的和。
我們是把每個數字的因數都分爲了2部分(小於等於sq和大於sq的兩部分)(sq = 4)
對於數字1,有1個因數(1),我們簡單乘以2,多計算了1次1;
對於數字2,有2因數(1,2),我們簡單乘以2,多計算了1次1,1次2;
對於數字3,有2因數(1,3),我們簡單乘以2,多計算了1次1,1次3;
對於數字4,有2因數(1,2,4),我們簡單乘以2,多計算了1次1,1次2,1次4;
對於數字5,有2因數(1,5),我們簡單乘以2,正好;
對於數字6,有2因數(1,2,3,6),我們簡單乘以2,多計算了1次2,1次3;
對於數字7,有2因數(1,7),我們簡單乘以2,正好;
對於數字8,有2因數(1,2,4,8),我們簡單乘以2,多計算了1次2,1次4;
對於數字9,有2因數(1,3,9),我們簡單乘以2,多計算了1次3;
對於數字10,有2因數(1,2,5,10),我們簡單乘以2,正好;
對於數字11,有2因數(1,11),我們簡單乘以2,正好;
對於數字12,有2因數(1,2,3,4,6,12),我們簡單乘以2,1次3,1次4;
對於數字13,有2因數(1,13),我們簡單乘以2,正好;
對於數字14,有2因數(1,2,7,14),我們簡單乘以2,正好;
對於數字15,有2因數(1,3,5,15),我們簡單乘以2,正好;
對於數字16,有2因數(1,2,4,8,16),我們簡單乘以2,多計算了1次4。
加起來正好是1~sq這sq個因數,每一個都多計算了sq次。所以我們一共多計算了sq*sq次
所以該方法的正確結果應爲,其中sq爲x的算數平方根。
【代碼】
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<memory.h>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<array>
#include<deque>
#include<list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define mem(array) memset((array),0,sizeof((array)))
#define Qsort(array,len,cmp) qsort(array,len,sizeof(array[0]),cmp)
#define inf 0x7fffffff
#define MAXN 10+10000
using namespace std;
int main()
{
int q;
int x;
long long ans;
while(cin>>q){
for(int t = 0; t < q; ++t){
ans = 0;
scanf("%d",&x);
int sq = sqrt(x);
for(int i = 1; i <= sq; ++i){
ans += x/i;
}
cout << 2*ans -sq*sq << endl;
}
}
return 0;
}
題目來源於 牛客網