牛客练习赛25 因数个数和(贡献法)

题意:q次询问,每次给一个x,问1到x的因数个数的和。

思路:考虑1到x的数的因子为1有x/1,因子为2有x/2,……,所以要求的就是\sum_{i=1}^{x}x/i,因为数据是1e9,这样写绝对超时。我们换一个角度,相等的因子个数应该在某个特定的区间出现,比如x=12,有1 ,1 2,1 3,1 2 4,15,1 2 3 6,17,1 2 4 8,1 3 9,1 2 5 10,1 11,1 2 3 4 6 12。对应的因子个数为:1,2,2,3,2,4,2,4,3,4,2,6。ans=12+6+4+3+2+2+1+1+1+1+1+1。

从ans式子可以看出,12/5和12/6都是2,12/7和12/8和……12/12都是1,对应的区间为【5,6】,【7,12】。这些区间的l和r是可以算出来的,令i从1开始,r=x/(x/i),括号的x/i可以取整,也就可以找到r的最大值(因为x/i取整肯定小于x/i),再令i=r+1,继续操作就行了。

#include
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int maxn=200005;
const double eps=1e-8;
const double PI = acos(-1.0);
#define lowbit(x) (x&(-x))
int main()
{
    int q;
    cin>>q;
    for(int i=0; i>x;
        ll sum=0;
        for(int i=1,r; i<=x; i=r+1)
        {
            r=x/(x/i);
            sum+=1ll*(x/i)*(r-i+1);
        }
        printf("%lld\n",sum);
    }
    return 0;
}

 

你可能感兴趣的:(牛客,数论)