基础莫比乌斯反演
基础莫比乌斯反演#
莫比乌斯函数#
对于
若 则
若 则
否则
线性筛莫比乌斯函数#
inline void get_mu(){
mu[1]=not_p[1]=1;
for(int i=2;i<N;++i){
if(!not_p[i]){
p[++cnt]=i;
mu[i]=-1;
}
for(int j=1;j<=cnt&&i*p[j]<N;++j){
not_p[i*p[j]]=1;
if(i%p[j]==0) break;
else mu[i*p[j]]=-mu[i];
}
}
}
基本公式#
so:
还有:
p.s. 后文中除法均默认向下取整
对于约数个数函数 有如下性质:
整除分块#
对于
因为有许多 的值相同,每一个值相同的块最后一个数是 因此可以把其分成 块再预处理
这个式子的结果可以在 的时间内求出
for(int l=1,r;l<=n;l=r+1){
r=n/(n/l);
ans+=(r-l+1)*(n/l);
}
P2257 YY的GCD#
题意:
求:
思路:
枚举一个
同时除以
已知
so,反演一下
枚举 ,由于 ,所以 均为 的倍数
但过不了,考虑优化
令 ,有
枚举 ,往前提
后面一大部分可以预处理
处理一下就可
注意直接枚举会
所以加一个整除分块和就行
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-1;
ch=getchar();
}
while(isdigit(ch)){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
const int N=1e7+1;
#define int long long
int cnt;
int sum[N],f[N];
int mu[N],p[N];
bool not_p[N];
inline void get_mu(){
mu[1]=not_p[1]=1;
for(int i=2;i<N;++i){
if(!not_p[i]){
p[++cnt]=i;
mu[i]=-1;
}
for(int j=1;j<=cnt&&i*p[j]<N;++j){
not_p[i*p[j]]=1;
if(i%p[j]==0) break;
else mu[i*p[j]]=-mu[i];
}
}
for(int i=1;i<=cnt;++i)
for(int j=1;p[i]*j<N;++j)
f[j*p[i]]+=mu[j];
for(int i=1;i<N;++i)
sum[i]=sum[i-1]+f[i];
}
inline int solve(int x,int y){
int ans=0;
if(x>y) swap(x,y);
for(int i=1,j=0;i<=x;i=j+1){
j=min(x/(x/i),y/(y/i));
ans+=(sum[j]-sum[i-1])*(x/i)*(y/i);
}
return ans;
}
signed main(){
int T=read();
get_mu();
while(T--) cout<<solve(read(),read())<<endl;
}
P3455 ZAP-Queries#
题意:
给你 ,求
思路:
和之前几乎一摸一样
用一个整除分块搞搞就完事
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-1;
ch=getchar();
}
while(isdigit(ch)){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
const int N=5e4+1;
int sum[N];
int cnt,mu[N],p[N];
bool not_p[N];
inline void get_mu(){
mu[1]=not_p[1]=1;
for(int i=2;i<N;++i){
if(!not_p[i]){
p[++cnt]=i;
mu[i]=-1;
}
for(int j=1;j<=cnt&&i*p[j]<N;++j){
not_p[i*p[j]]=1;
if(i%p[j]==0) break;
else mu[i*p[j]]=-mu[i];
}
}
for(int i=1;i<N;++i) sum[i]=sum[i-1]+mu[i];
}
inline int solve(int x,int y,int k){
int ans=0;
if(x>y) swap(x,y);
for(int l=1,r=0;l<=x;l=r+1){
r=min(x/(x/l),y/(y/l));
ans+=(sum[r]-sum[l-1])*(x/(l*k))*(y/(l*k));
}
return ans;
}
signed main(){
get_mu();
int T=read();
while(T--){
int x=read(),y=read(),k=read();
cout<<solve(x,y,k)<<endl;
}
}
P2522 Problem b#
题意:
求
思路:
不再推一遍了
但是有一些不同的是,这题多一个容斥
假如 是式子
的值
那么最终的结果
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-1;
ch=getchar();
}
while(isdigit(ch)){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
const int N=5e4+1;
int sum[N];
int cnt,mu[N],p[N];
bool not_p[N];
inline void get_mu(){
mu[1]=not_p[1]=1;
for(int i=2;i<N;++i){
if(!not_p[i]){
p[++cnt]=i;
mu[i]=-1;
}
for(int j=1;j<=cnt&&i*p[j]<N;++j){
not_p[i*p[j]]=1;
if(i%p[j]==0) break;
else mu[i*p[j]]=-mu[i];
}
}
for(int i=1;i<N;++i) sum[i]=sum[i-1]+mu[i];
}
inline int solve(int x,int y,int k){
int ans=0;
if(x>y) swap(x,y);
for(int l=1,r=0;l<=x;l=r+1){
r=min(x/(x/l),y/(y/l));
ans+=(sum[r]-sum[l-1])*(x/(l*k))*(y/(l*k));
}
return ans;
}
signed main(){
get_mu();
int T=read();
while(T--){
int a=read(),b=read(),c=read(),d=read(),k=read();
cout<<solve(b,d,k)-solve(b,c-1,k)-solve(a-1,d,k)+solve(a-1,c-1,k)<<endl;
}
}
P3327 约数个数和#
题意:
设 为 的约数个数,给定 ,求
思路:
已知
so,要求的就是
直接枚举 的因数
反演一下
改为枚举
减少枚举次数
结合一下
接下来预处理一个函数 ,则
然后整除分块就行
#include<bits/stdc++.h>
using namespace std;
inline int read(){
int x=0,f=1;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-1;
ch=getchar();
}
while(isdigit(ch)){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
const int N=5e4+1;
#define int long long
int cnt;
int sum[N],f[N];
int mu[N],p[N];
bool not_p[N];
inline void get_mu(){
mu[1]=not_p[1]=1;
for(int i=2;i<N;++i){
if(!not_p[i]){
p[++cnt]=i;
mu[i]=-1;
}
for(int j=1;j<=cnt&&i*p[j]<N;++j){
not_p[i*p[j]]=1;
if(i%p[j]==0) break;
else mu[i*p[j]]=-mu[i];
}
}
for(int i=1;i<N;++i) sum[i]=sum[i-1]+mu[i];
for(int i=1;i<N;++i)
for(int l=1,r;l<=i;l=r+1){
r=i/(i/l);
f[i]+=(r-l+1)*(i/l);
}
}
inline int solve(int x,int y){
int ans=0;
if(x>y) swap(x,y);
for(int l=1,r=0;l<=x;l=r+1){
r=min(x/(x/l),y/(y/l));
ans+=(sum[r]-sum[l-1])*f[x/l]*f[y/l];
}
return ans;
}
signed main(){
int T=read();
get_mu();
while(T--){
int n=read(),m=read();
cout<<solve(n,m)<<endl;
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现