「51nod1190」最小公倍数之和 V2 题解
本文网址:https://www.cnblogs.com/zsc985246/p/17389399.html ,转载请注明出处。
前置知识
2023/5/18update:更正了第 个公式。
莫比乌斯函数定义:
对于一个数 ,其中 为素数,那么
莫比乌斯反演的一种形式:。
积性函数:对于任意互质的正整数 和 有 的数论函数。
数论函数:定义域为正整数,陪域为复数的函数。
题目大意
给定 ,求 。
。
思路
看到 想到 。
然后对于分数,一个常用的套路就是枚举因数。
然后我们根据莫比乌斯反演,直接将 换掉。
然后发现最后面的那一坨其实就是等差数列求和,直接拆开就好。
我们调换一下枚举的顺序,先枚举一个 ,然后再枚举 。
找出 的因数就可以解决前面的式子,所以现在我们只需要处理 。
由于 的范围是 ,我们不能直接预处理 ,所以需要另寻方法。
我们令 。
所以 是积性函数。
而我们又知道对一个质数 和任意正整数 ,。
所以如果 ,其中 为素数,那么 。
那么我们就可以在枚举因数 时直接计算 的值了。
代码实现
多测不清空,爆零两行泪。
#include<bits/stdc++.h>
#define ll long long
#define For(i,a,b) for(ll i=(a);i<=(b);++i)
#define Rep(i,a,b) for(ll i=(a);i>=(b);--i)
const ll N=1e6+10;
using namespace std;
const ll mod=1e9+7;
ll vis[N],tot,p[N];
void init(ll n){//质数筛
For(i,2,n){
if(!vis[i])p[++tot]=i;
For(j,1,tot){
if(i*p[j]>n)break;
vis[i*p[j]]=1;
if(i%p[j]==0)break;
}
}
}
ll cnt,t[N],num[N];//t为质因数,num为出现的个数
void solve(ll x){//质因数分解
for(ll i=1;p[i]*p[i]<=x;i++){
if(x%p[i]==0){
t[++cnt]=p[i];
num[cnt]=0;
while(x%p[i]==0)num[cnt]++,x/=p[i];
}
}
if(x>1)t[++cnt]=x,num[cnt]=1;
}
ll a,b,ans;
void dfs(ll x,ll d,ll s){//第x个质因数,目前枚举的因数为d,f(d)=s
if(x>cnt){//按公式计算答案
ll t1=b/d,t2=(a+d-1)/d;
ans=(ans+(t1+t2)*(t1-t2+1)*s%mod+mod)%mod;
return;
}
dfs(x+1,d,s);//不选当前质因数
s=s*(1-t[x]);//积性函数直接计算
For(i,1,num[x]){//选i个当前质因数
d*=t[x];
dfs(x+1,d,s);
}
}
void mian(){
scanf("%lld%lld",&a,&b);
cnt=ans=0;//记得清空
solve(b);
dfs(1,1,1);
printf("%lld\n",ans*500000004%mod*b%mod);//500000004是2在模1000000007下的逆元
}
int main(){
init(50000);
int T=1;
scanf("%d",&T);
while(T--)mian();
return 0;
}
尾声
如果你发现了问题,你可以直接回复这篇题解
如果你有更好的想法,也可以直接回复!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现