洛谷 P2261 [CQOI2007]余数求和

12 篇文章 0 订阅
1 篇文章 0 订阅

前两天肝了整整两天的FFT,博客暂咕
今天打算先肝个莫队,于是复习一下整除分块

题面:
给出 n , k ( 1 ≤ n , k ≤ 1 0 9 ) n,k(1\le n,k\le 10^9) n,k(1n,k109),求
∑ i = 1 n k m o d    i \large\sum\limits_{i=1}^{n}k\mod i i=1nkmodi
推一波公式:
∑ i = 1 n k m o d    i = ∑ i = 1 n k − i ∗ ⌊ k i ⌋ = n k − ∑ i = 1 n i ∗ ⌊ k i ⌋ \begin{aligned} &\sum\limits_{i=1}^{n}k\mod i\\ =&\sum\limits_{i=1}^{n}k-i*\lfloor\frac{k}{i}\rfloor\\ =&nk-\sum\limits_{i=1}^{n}i*\lfloor\frac{k}{i}\rfloor\\ \end{aligned} ==i=1nkmodii=1nkiiknki=1niik
推到这里,观察一下 ⌊ k i ⌋ \lfloor\frac{k}{i}\rfloor ik,发现:到了后面 i i i大的时候 ⌊ k i ⌋ \lfloor\frac{k}{i}\rfloor ik可能会保持不变!
重点来看 ⌊ k i ⌋ \lfloor\frac{k}{i}\rfloor ik会在什么区间内保持不变:
⌊ k i ⌋ = ⌊ k j ⌋ = q   ( i < j ) \lfloor\frac{k}{i}\rfloor=\lfloor\frac{k}{j}\rfloor=q~(i<j) ik=jk=q (i<j)
则有 q i + x = q j + y = k   ( 0 ≤ x < i , 0 ≤ y < j ) qi+x=qj+y=k~(0\le x<i,0\le y<j) qi+x=qj+y=k (0x<i,0y<j)
最极端的情况便是 y = 0 y=0 y=0
q i + x = q j = k qi+x=qj=k qi+x=qj=k
肉眼可见 j = k q j=\frac{k}{q} j=qk
考虑到可能 q ∤ j q\nmid j qj
所以 j = ⌊ k q ⌋ j=\lfloor\frac{k}{q}\rfloor j=qk
对于每一个 x x x,它所在的 ⌊ k i ⌋ \lfloor\frac{k}{i}\rfloor ik区间上界就是 k ⌊ k x ⌋ \frac{k}{\lfloor\frac{k}{x}\rfloor} xkk
这样就可以通过等差数列对每一块的 i ∗ ⌊ k i ⌋ i*\lfloor\frac {k}{i}\rfloor iik进行计算了
每块计算公式:
( l + r ) ∗ ( r − l + 1 ) 2 ∗ ( k / l ) \frac{(l+r)*(r-l+1)}{2}*(k/l) 2(l+r)(rl+1)(k/l)
肉眼可见初始块一定是 [ 1 , 1 ] [1,1] [1,1]
递推式: r = ⌊ k ⌊ k l ⌋ ⌋ , l = r + 1 r=\lfloor\frac{k}{\lfloor\frac{k}{l}\rfloor}\rfloor,l=r+1 r=lkk,l=r+1

有一个细节:
如果 l > k l>k l>k,那么 ⌊ k i ⌋ = 0 \lfloor\frac{k}{i}\rfloor=0 ik=0,会导致除以零
由此我们要加一个特判

#include<cstdio>
using namespace std;
inline int min(const int a,const int b)
{return a<b?a:b;}
int main()
{
	int n,k;
	scanf("%d%d",&n,&k);
	long long ans=0;
	for(int l=1,r=1;l<=n;l=r+1,r=k>l?min(n,k/(k/l)):n)
		ans+=1ll*(l+r)*(r-l+1)/2*(k/l);
	printf("%lld",1ll*n*k-ans);
	return 0;
}

这就是整除分块的一种

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值