传送门
首先是一个比较容易理解的数论知识:
在 n 以 内 所 有 数 的 因 数 和 = ∑ i = 1 n n / i 在n以内所有数的因数和=\sum_{i=1}^{n}n/i 在n以内所有数的因数和=i=1∑nn/i
那么 x x x是 n n n的因数,那么 n / x n/x n/x肯定也是 n n n的因数
我们可以将上面的公式变为( w w w为 n n n的算术平方根)
( ∑ i = 1 w n / i ) ∗ 2 (\sum_{i=1}^{w}n/i)*2 (i=1∑wn/i)∗2
但当我们自信满满的去做时,会发现答案太大了,这是为什么呢
——很显然,当 n = 16 n=16 n=16, i = 4 i=4 i=4时,我们就会多算一次 4 4 4
而其他的平方数也是如此
故我们应减去 w w w,但这样还是 W A WA WA
这又是为什么呢
我们不妨来举个例子:
对于数字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 w 1~w 1 w这 w w w个因数,每一个都多计算了 w w w次。所以我们一共多计算了 w 2 w^2 w2次
所以将我们以上所有内容总结起来,得出 A C AC AC公式:
( ∑ i = 1 w n / i ) ∗ 2 − w 2 (\sum_{i=1}^{w}n/i)*2-w^2 (i=1∑wn/i)∗2−w2
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LL long long
#define h happy
#define XJQ 牛逼
#define HSZGB 欠老子400块
using namespace std;
inline LL read() {
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
int main()
{
int q=read();
LL ans=0;
while(q--)
{
int x=read();
int s=sqrt(x);
ans=0;
for(int i=1;i<=s;i++) ans+=x/i;
printf("%lld\n",ans*2-s*s);
}
return 0;
}