整除分块学习笔记
搬运自我的洛谷文章整除分块学习笔记。
前言
本文是作者学习整除分块后的一些心得,可能有所不足,如有错误,望读者指正。
分块技巧
本文以求解问题:
为例讲述整除分块。
易知当
假设
令
将两个式子化为整式可得
又
又
然后
显然当
简单推导即可:
用等差数列结合整除分块做即可。
#include<bits/stdc++.h> #define int unsigned long long using namespace std; int n,k,L=1,R,ans; signed main(){ cin>>n>>k; ans=n*k; while(L<=n){ if(k/L>0) R=min(k/(k/L),n); else R=n; //求右端点 ans-=(R-L+1)*(L+R)/2*(k/L); //等差数列 L=R+1; } cout<<ans; return 0; }
非常有学习意义的一题。
考虑将
我们考虑枚举合法的
显然
故总答案为
但
等等,
但是还有问题,我们无法直接通过 c%2!=0&&c%5!=0
判断
那怎么办?通过容斥原理可以解决。
但是这样的函数并不是很好求。但是将
所以问题就迎刃而解了。
#include<bits/stdc++.h> #define int long long using namespace std; int n,L=1,R,res; int Cal_1(int range){//容斥求方案 return range-range/2-range/5+range/10; } int Cal_2(int x){//求出[1,x]中只含2,5因子的数的数量 int ans=0; for(int i=1;i<=x;i*=2) for(int j=i;j<=x;j*=5) ans++; return ans; } signed main(){ cin>>n; while(L<=n){ int R=n/(n/L); //整除分块基本操作:R=n/(n/L) res+=(Cal_1(R)-Cal_1(L-1))*Cal_2(n/L)*(n/L);//计算答案 L=R+1;//跳至下一分块 } cout<<res; return 0; }
本文作者:xuchuhan
本文链接:https://www.cnblogs.com/xch0730/p/18668274/number-theory-block
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步