当前位置:网站首页>数论分块(整除分块)
数论分块(整除分块)
2022-04-23 06:21:00 【Zimba_】
前言:
断更太久,已经忘了博客怎么写了。。
这篇博客用来介绍带整除式子的快速求解办法。
符号说明:
⌊ a b ⌋ \left \lfloor \frac{a}{b}\right \rfloor ⌊ba⌋ : a a a除以 b b b向下取整。
⌈ a b ⌉ \left \lceil \frac{a}{b}\right \rceil ⌈ba⌉ : a a a除以 b b b向上取整。
∑ i = 1 n f ( i ) \sum_{i=1}^{n}f(i) ∑i=1nf(i) : 累加符号,表示 f ( 1 ) + f ( 2 ) + … + f ( n ) f(1)+f(2)+…+f(n) f(1)+f(2)+…+f(n)。
问题:
求解 ∑ i = 1 n ⌊ n i ⌋ \sum_{i=1}^{n}\left \lfloor \frac{n}{i}\right \rfloor ∑i=1n⌊in⌋,其中 1 ⩽ n ⩽ 1 e 12 1\leqslant n \leqslant 1e12 1⩽n⩽1e12。
正文:
首先,不难发现有一个o(n)的暴力。
我们需要一个 n \sqrt{n} n的做法。
我们可以先举例观察,我们举 n = 10 n=10 n=10,然后枚举从 1 1 1到 n n n枚举 i i i,观察 ⌊ n i ⌋ \left \lfloor \frac{n}{i}\right \rfloor ⌊in⌋的值。
1 1 1 2 2 2 3 3 3 4 4 4 5 5 5 6 6 6 7 7 7 8 8 8 9 9 9 10 10 10
10 10 10 5 5 5 3 3 3 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
就是上面这个样子。
不难发现也不难证明,相同的数都是连续的,可以把它分成一块一块值相同的段。那么我们可以利用这个性质,对于每一块,将这个块的数字乘上块的长度,就可以求解这一块的和了。
现在还有两个问题要解决。
一个是块的数量,一个是如何快速找到块的两端。
首先块的数量,对于 i i i从 1 1 1到 n n n取值, ⌊ n i ⌋ \left \lfloor \frac{n}{i}\right \rfloor ⌊in⌋的值的种数不会超过 2 n 2\sqrt{n} 2n,也就是块的数量不会超过 2 n 2\sqrt{n} 2n。
证明其实很容易,
嗯,可以证,前 n \sqrt{n} n个 i i i最多有 n \sqrt{n} n种值,而当 i i i大于 n \sqrt{n} n时,取值一定小于 n \sqrt{n} n,所以不超过 2 n 2\sqrt{n} 2n(摘自ztc口糊)。
那么第二个问题,快速找到块的端点。
当某一块的左端点为 l l l,那么它的右端点 r r r就是 ⌊ n ⌊ n l ⌋ ⌋ \left \lfloor \frac{n}{\left \lfloor \frac{n}{l}\right \rfloor}\right \rfloor ⌊⌊ln⌋n⌋。 这个就更好证了。
也可以理解成,已知 i i i,那么与 i i i相同的块的右端点就是 ⌊ n ⌊ n i ⌋ ⌋ \left \lfloor \frac{n}{\left \lfloor \frac{n}{i}\right \rfloor}\right \rfloor ⌊⌊in⌋n⌋
也就是说,当 i i i的取值在 l l l到 r r r之间时,式子的结果是一样的,那么只要再乘上区间长度 ( r − l + 1 ) (r-l+1) (r−l+1)即可。
最后再对于原问题,上模板代码:(有取模的加取模)
ll ans=0;
for(ll l=1,r;l<=n;l=r+1)
{
r=n/(n/l);
ans+=(r-l+1)*(n/l);
}
例题及应用:
再拓展几个例题,有,但不全,还是要去多找题做。
问题1:
已知 w w w和 n n n,求解 ∑ i = 1 n ⌊ w i ⌋ \sum_{i=1}^{n}\left \lfloor \frac{w}{i}\right \rfloor ∑i=1n⌊iw⌋,其中 1 ⩽ n , w ⩽ 1 e 12 1\leqslant n,w \leqslant 1e12 1⩽n,w⩽1e12。
解:
与原题不同,这里的枚举上界 n n n不再作为被除数。
那么在计算右端点 r r r的时候,会引发一个细节问题。
看式子, r = w / ( w / l ) r=w/(w/l) r=w/(w/l)。会出现两个种特殊情况。
一种是 w / l = = 0 w/l==0 w/l==0,此时再调用这个式子就会出现除 0 0 0的情况,导致RE。
还有一种是,计算结果 r > n r>n r>n,此时右端点不在边界内了。
要把这两种情况考虑进去,在原代码的基础上进行修改。
ll ans=0;
for(ll l=1,r;l<=n;l=r+1)
{
if(w/l)r=w/(w/l);
else r=n;
r=min(r,n);
ans+=(r-l+1)*(w/l);
}
问题2:
已知 a , b a,b a,b和 n n n,求解 ∑ i = 1 n ⌊ a i ⌋ ⌊ b i ⌋ \sum_{i=1}^{n}\left \lfloor \frac{a}{i}\right \rfloor\left \lfloor \frac{b}{i}\right \rfloor ∑i=1n⌊ia⌋⌊ib⌋,其中 1 ⩽ n , a , b ⩽ 1 e 12 1\leqslant n,a,b \leqslant 1e12 1⩽n,a,b⩽1e12。
解:
在原问题的基础上多乘了一个,不过别怕,只不过从原来 2 a 2\sqrt{a} 2a个断点,变成了 2 a + 2 b 2\sqrt{a}+2\sqrt{b} 2a+2b个断点,复杂度仍然是根号级别的。
我们只要每次找最近的那个断点即可。
ll ans=0;
for(ll l=1,r,r1,r2;l<=n;l=r+1)
{
if(a/l)r1=a/(a/l);
else r1=n;
if(b/l)r2=b/(b/l);
else r2=n;
r=min(r1,r2)
r=min(r,n);
ans+=(r-l+1)*(a/l)*(b/l);
}
问题3:
已知 w w w和 n n n,求解 ∑ i = 1 n ⌈ w i ⌉ \sum_{i=1}^{n}\left \lceil \frac{w}{i}\right \rceil ∑i=1n⌈iw⌉,其中 1 ⩽ n , w ⩽ 1 e 12 1\leqslant n,w \leqslant 1e12 1⩽n,w⩽1e12。
解:
这是向上取整的,不好找到想原来一样的结论,但是我们可以把向上取整转化为向下取整。
⌈ w i ⌉ = ⌊ w + i − 1 i ⌋ = ⌊ w − 1 i ⌋ + 1 \left \lceil \frac{w}{i}\right \rceil=\left \lfloor \frac{w+i-1}{i}\right \rfloor=\left \lfloor \frac{w-1}{i}\right \rfloor+1 ⌈iw⌉=⌊iw+i−1⌋=⌊iw−1⌋+1
就可以轻松解决了。
ll ans=0;
for(ll l=1,r;l<=n;l=r+1)
{
if((w-1)/l)r=(w-1)/((w-1)/l);
else r=n;
r=min(r,n);
ans+=(r-l+1)*((w-1)/l+1);
}
问题5:
已知 w w w和 n n n,求解 ∑ i = 1 n i ⌊ w i ⌋ \sum_{i=1}^{n}i\left \lfloor \frac{w}{i}\right \rfloor ∑i=1ni⌊iw⌋,其中 1 ⩽ n , w ⩽ 1 e 12 1\leqslant n,w \leqslant 1e12 1⩽n,w⩽1e12。
解:
多乘了一个 i i i,与原来不同的就是,这次我们不能再乘 r − l + 1 r-l+1 r−l+1了,前面 r − l + 1 r-l+1 r−l+1的本质其实是那一段的区间和,这时候我们要乘上的是区间 i i i的求和。(因为这段区间里 ⌊ w i ⌋ \left \lfloor \frac{w}{i}\right \rfloor ⌊iw⌋是一样的,相当于一个常系数,所以才可以这么乘的)
ll ans=0;
for(ll l=1,r;l<=n;l=r+1)
{
if(w/l)r=w/(w/l);
else r=n;
r=min(r,n);
ans+=(r-l+1)*(l+r)/2*(w/l);
}
问题6:模和积
求 ∑ i = 1 n ∑ j = 1 m ( n m o d i ) × ( m m o d j ) , i ≠ j \sum_{i=1}^{n}\sum_{j=1}^{m}(n\;mod\;i)\times (m\;mod\;j),i\neq j ∑i=1n∑j=1m(nmodi)×(mmodj),i=j模 19940417 19940417 19940417的值。
其中 1 ⩽ n , m ⩽ 1 e 9 1\leqslant n,m \leqslant 1e9 1⩽n,m⩽1e9。
解:
首先要知道 ( n m o d i ) = n − i × ⌊ w i ⌋ (n\;mod\;i)=n-i\times \left \lfloor \frac{w}{i}\right \rfloor (nmodi)=n−i×⌊iw⌋。
然后开始化式子,注意 i ≠ j i\neq j i=j的条件不能忽略。
化好公式后,就可以写了。
#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
typedef long long ll;
const ll mod=19940417;
typedef pair<int,int> P;
const ll MAXN=1000000;
const ll inv6=3323403;
ll sum(ll l,ll r,ll flag)
{
if(flag==1)
{
return (r-l+1)*(l+r)/2%mod;
}
else
{
return (r*(r+1)%mod*(2*r+1)%mod*inv6%mod-(l-1)*l%mod*(2*l-1)%mod*inv6%mod+mod)%mod;
}
}
int main()
{
ll n,m;
scanf("%lld%lld",&n,&m);
ll sum1=0;
for(ll l=1,r;l<=n;l=r+1)
{
r=n/(n/l);
sum1=(sum1+n*(r-l+1)%mod-sum(l,r,1)*(n/l)%mod+mod)%mod;
}
ll sum2=0;
for(ll l=1,r;l<=m;l=r+1)
{
r=m/(m/l);
sum2=(sum2+m*(r-l+1)%mod-sum(l,r,1)*(m/l)%mod+mod)%mod;
}
ll nm=min(n,m);
ll sum3=0;
for(ll l=1,r,r1,r2;l<=nm;l=r+1)
{
if(n/l)r1=n/(n/l);
else r1=nm;
if(m/l)r2=m/(m/l);
else r2=nm;
r=min(r1,r2);
r=min(r,nm);
sum3=(sum3+n*m%mod*(r-l+1)%mod-(n*(m/l)%mod+m*(n/l)%mod)*sum(l,r,1)%mod+sum(l,r,2)*(n/l)%mod*(m/l)%mod+mod)%mod;
}
ll ans=(sum1*sum2-sum3+mod)%mod;
printf("%lld\n",ans);
return 0;
}
问题7:余数求和
解:
问题6的简化版本,就不贴代码了。
版权声明
本文为[Zimba_]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_43785386/article/details/104410046
边栏推荐
猜你喜欢
Solution of self Networking Wireless Communication intercom system in Beifeng oil and gas field
Intelligent communication solution of Hainan Phoenix Airport
How does the public and Private Integrated walkie talkie realize cooperative work under multi-mode communication?
学习笔记6-几种深度学习卷积神经网络的总结
ES6之箭头函数细谈
Us photo cloud editing helps BiliBili upgrade its experience
可视化常见问题解决方案(八)数学公式
javscript获取文件真实后缀名
直观理解熵
Background management system framework, there is always what you want
随机推荐
记录一个查询兼容性的网站,String.replaceAll()兼容性报错
简单易懂的子集dp
华为云MVP邮件
LATEX公式注意事项
P1390 公约数的和(莫比乌斯反演)
Metro wireless intercom system
数论之拓展欧几里得
免费开源农业物联网云平台(Version:3.0.1)
免费开源智能充电桩物联网SAAS云平台
xdotool按键精灵
SQL练习第一题
枫桥学院开元名庭酒店DMR系统解决方案
Typora语法详解(一)
直观理解熵
Object.create()原理,Object.create()规范,手写Object.create(),Object.create()用法
免费开源充电桩物联网云平台
利用mysql-binlog恢复数据
学习资料
vim+ctags+cscpope开发环境搭建指南
快速下载vscode的方法