【网络赛一:整除分块】C:Fear Factoring

难度

3 / 10 3/10 3/10
不学整除分块自己推很难的一题

题意

定义 F ( n ) = ∑ n i = 1 [    i    ∣    x    ] × i F(n)=\underset{i=1}{\overset{n}{\sum}}\big[\;i\;\big|\;x\;\big]\times i F(n)=i=1n[ix]×i 表示为 n n n 的所有因子的和。

S = ∑ a ≤ n ≤ b F ( n ) S=\underset{a\le n\le b}{\sum}F(n) S=anbF(n)

数据范围

1 ≤ a ≤ b ≤ 1 0 12 1\le a\le b\le 10^{12} 1ab1012
b − a ≤ 1 0 6 b-a\le 10^6 ba106

思路

【1】首先考虑暴力枚举

S S S 即求    ∑ 1 ≤ n ≤ b F ( n ) − ∑ 1 ≤ n ≤ a − 1 F ( n ) \;\underset{1\le n\le b}{\sum}F(n) - \underset{1\le n\le a-1}{\sum}F(n) 1nbF(n)1na1F(n)

G ( n ) = ∑ 1 ≤ k ≤ n F ( k ) G(n)=\underset{1\le k\le n}{\sum}F(k) G(n)=1knF(k)

你每个值都是 O ( N ) O(N) O(N) 枚举判断累加答案,时间复杂度 O ( b ) = 1 0 12 O(b)=10^{12} O(b)=1012 ,不可行。

【2】考虑整除分块
普通的整除分块是 g ( n ) = ∑ n i = 1 ⌊ n i ⌋ g(n)=\underset{i=1}{\overset{n}{\sum}}\lfloor\frac{n}{i}\rfloor g(n)=i=1nin
但是易得我们所需求的分块为 G ( n ) = ∑ n i = 1 ⌊ n i ⌋ × i G(n)=\underset{i=1}{\overset{n}{\sum}}\lfloor\frac{n}{i}\rfloor\times i G(n)=i=1nin×i
于是我就不会了。。

我们枚举 G ( 12 ) G(12) G(12) 易得

i123456789101112
x i \frac{x}{i} ix1264322111111

很多连续的 i i i 的情况下的系数 x i \frac{x}{i} ix 也是相同的。
我们需要枚举每一个不同系数的左端点 l l l 和右端点 r r r
首先,初始化 l = 1 l=1 l=1
对于每一个 l l l ,我们的新的区间的系数为 ⌊ x l ⌋ \lfloor\frac{x}{l}\rfloor lx
我们需要找到最大的 r r r 满足 ⌊ x l ⌋ = ⌊ x r ⌋ \lfloor \frac{x}{l}\rfloor=\lfloor \frac{x}{r} \rfloor lx=rx
那么易得此时的 r = ⌊ x ⌊ x l ⌋ ⌋ r=\lfloor \frac{x}{\lfloor\frac{x}{l}\rfloor}\rfloor r=lxx
那么我们需要累加多少个 x i \frac{x}{i} ix 的答案呢?
显然为 ∑ r i = l ⌊ x l ⌋ × i = ⌊ x l ⌋ ∑ r i = l    i = ⌊ x l ⌋ × ( l + r ) ( r − l + 1 ) 2 \underset{i=l}{\overset{r}{\sum}}\lfloor\frac{x}{l}\rfloor\times i=\lfloor\frac{x}{l}\rfloor \underset{i=l}{\overset{r}{\sum}}\;i=\lfloor\frac{x}{l}\rfloor\times \frac{(l+r)(r-l+1)}{2} i=lrlx×i=lxi=lri=lx×2(l+r)(rl+1)

算完这区间,明显易得 l l l 更新为此时的 r + 1 r+1 r+1

核心代码

时间复杂度 : O ( log ⁡ b ) O(\log b) O(logb)
Time(s):125MS

/*
 _            __   __          _          _
| |           \ \ / /         | |        (_)
| |__  _   _   \ V /__ _ _ __ | |     ___ _
| '_ \| | | |   \ // _` | '_ \| |    / _ \ |
| |_) | |_| |   | | (_| | | | | |___|  __/ |
|_.__/ \__, |   \_/\__,_|_| |_\_____/\___|_|
        __/ |
       |___/
*/
#define ll unsigned long long			/// 不开 ull 会 WA 一个点
ll cal(ll x){
    ll l=1,r=0,ans=0;
    while(l<=x){
        r=x/(x/l);
        ans+=(x/l)*(r-l+1)*(l+r)/2;
        l=r+1;
    }
    return ans;
}
int main()
{
    ll a,b;
    cin >> a >> b;
    cout << cal(b) - cal(a-1) << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值