即求:
我们可以先对原式转化一下:,
在i的一定区间上会保持一个固定的值
比如,我们求一下13对小于等于它的数相除后取地板:13、6、4、3、2、2、1、1、1、1、1、1、1
在这里[5,6]上都是一个固定值2,[7,13]上都是一个固定的值1,在这些区间上是等差数列
所以我们只需要找到每个区间的首项和末项就可以求出来,那么也就很容易得到
了
仔细想一想可以发现,每个区间的最后一项是,把这一项记作e,那么下一次的首项设为e+1,可以容易求得解
代码:
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
LL sum=0;
LL x;
scanf("%lld",&x);
LL s,e;
s=1,e=1;
while(e!=x)
{
e=x/(x/s);
sum=sum+(x/s)*(s+e)*(e-s+1)/2;
s=e+1;
}
sum=x*x-sum;
printf("%lld\n",sum);
}
return 0;
}
如果数据范围比较小我们可以找一下规律:
ans[i]与ans[i-1]是有关系的,ans[i]=ans[i-1]+i-2-(i的因子和)
代码:
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <vector>
using namespace std;
const int MAXN=100005;
typedef long long LL;
LL sum[MAXN];
LL ans[MAXN];
void init()
{
int i,j;
for(i=1;i<MAXN;i++)sum[i] =1;
sum[0] = 0 ;
for(i=2;i<MAXN/2;i++)
{
for(j=2*i;j<MAXN;j+=i)
sum[j]+=i;
}
}
void solve()
{
ans[1]=0;
ans[2]=0;
for(int i=3;i<MAXN;i++)
{
ans[i]=ans[i-1]+i-2-(sum[i]-1);
}
}