B Gym 101652P Fear Factoring
这题求 b , a之间 所有数包括他的因子和。
看一眼肯定知道是筛选所有的因子。
a,b不超过 1e6。a , b ,不超过 1e12,1e6*1e6刚好1e12
所以我们枚举 1-1e6所有的数 ,然后求分别以这个为因子会出现的次数。
然后用 ,a 出现的因子和 -b 里面出现的因子和。
加入我们要求 x=10 里面所有的因子和。
首先 10/1 =10 所有以1为因子的 另一个因子 最大是10.
枚举 一下好理解就是 1= 1*1 2=2*1 3=3*1 4=4*1 5=5*1 … 10=10*1.
就是 从 所有数和 (1 +2+3+4+……+10) (这个时候不用把 自己这个因子加进去,因为后面以其他数为因子还会再算一次,这样会重复)
然后 10/2=5 所有以 2为 因子的另一个因子最大是 5.
枚举一下:2=1*2,4=2*2,6=3*2,8=4*2,10=5*2;
所有数的和 就是 (1+2+3+4+5)
同理 10/3=3 所有以 3 为因子另一个因子和是 (1+2+3)
以此类推后面所有因子的和就可以得结果。
但是你会发现过不去样例 3 … … 因为你只枚举到了1e6 万一 x>1e6,会出现
以这个(1e6+1)为 因子的,另一个因子的和就没有加上去,所以就要反过来。
原本是确定一个因子 求另一个因子所有的数的和,这次我们就求一个因子总共出现多少次。
例如 x= 1e8,原本已经求了 以 1-1e6为因子然后另一个因子的和,就相当于,把出现少于 1e6次数以下的全部加上了。所以出现少于 1e6次以下的都不用加了,只需要以上的首先枚举 1-1e6;
1 x/1=1e8, 1出现了 1e 8 次前面以及算了 1e6次 所以 以 1为因子还需要加上的次数是 1e8-1e6, 和是 (1e8-1e6)*1;
同理 2 x/2=5e7,2出现了5e7次 所有数的和是 (5e7-1e6)*2;
以此类推 2 3 4 直到 1e6 因为a,b<1e12 ,所以 最多到 1e6不可能再多了,
还有一个问题如果 x=1e12, 求 以1为因子的时候 是 最大因子是1e12
求和的话是 (1+1e12)*1e12/2 这个明显炸longlong 了,如果你会开 int128后面就不用看了。
这个题目给的数据b-a不超过 1e6 ,可以直接求,k1=(b+i-1)/i (这个要向上取整) ,k2=a/i;
然后所有数的和是 (k2-k1+1)*(k2+k1)/2 这样就不会炸 long long
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main() {
ll b,a,res=0;
cin>>b>>a;
for(int i=1; i<=1e6; i++) {
ll k1=(b+i-1)/i,k2=a/i;
if(k1>k2)continue;
res+=(k2-k1+1)*(k2+k1)/2;
}
for(int i=1; i<=1e6; i++) {
if(n/i>=1e6) {
ll k=max((ll)1e6,(m-1)/i);
res+=(n/i-k)*i;
}
}
cout<<res<<endl;
}