洛谷 P4450 双亲数
小 D 是一名数学爱好者,他对数字的着迷到了疯狂的程度。
我们以 d = gcd(a, b) 表示 a 、b 的最大公约数,小D执著的认为,这样亲密的关系足可以用双亲来描述,此时,我们称有序数对 (a, b) 为d的双亲数。
与正常双亲不太相同的是,对于同一个 d ,他的双亲太多了 >_<
比如, (4, 6), (6, 4), (2, 100) 都是 2 的双亲数。
于是一个这样的问题摆在眼前,对于 0<a<=A, 0<b<=B ,有多少有序数对 (a, b) 是 d 的双亲数?
看完题目,就知道了是要求这个式子
A∑a=1B∑b=1 [gcd(a,b)=d]
考虑莫反,设f(x)={ 1(x=d) 0(x≠d)
那么我们要找到一个g使得f=g∗1,即f(x)=∑k|xg(x),因为1的逆是μ,所以g=f∗μ
g(x)=∑k|xμ(xk)[k=d]
g(x)=μ(xd)[d|x]
假设我们已经求出来g,那么就可以对式子进行化简了
A∑a=1B∑b=1 f(gcd(a,b))
A∑a=1B∑b=1∑k|a,k|b g(k)
min(A,B)∑k=1g(k) A∑a=1B∑b=1 [k|a] [k|b]
min(A,B)∑k=1g(k) ⌊Ak⌋ ⌊Bk⌋
然后对这个式子整除分块就可以了
至于g怎么求,我们把μ筛出来,然后就可以求每个g(x),再做一个前缀和就可以O(1)询问区间g的和了
Code
#include <iostream>
#include <cstdio>
#define N 1000000
using namespace std;
int a,b,d,mul[N+5],v[N+5],prime[N+5],cnt,g[N+5],sg[N+5];
long long ans;
void make()
{
mul[1]=1;v[1]=1;
for (int i=2;i<=N;i++) //线筛筛μ
{
if (!v[i])
{
prime[++cnt]=i;
mul[i]=-1;
}
for (int j=1;j<=cnt&&i*prime[j]<=N;j++)
{
v[prime[j]*i]=1;
if (i%prime[j]!=0)mul[i*prime[j]]=-mul[i];
else
{
mul[i*prime[j]]=0;
break;
}
}
}
for (int i=1;i<=N;i++) //处理g函数
if (i%d==0)
g[i]=mul[i/d];
for (int i=1;i<=N;i++) //前缀和
sg[i]=sg[i-1]+g[i];
}
int main()
{
cin>>a>>b>>d;
make();
if (a>b)swap(a,b);
for (int l=1,r;l<=a;l=r+1) 整除分块
{
r=min(a/(a/l),b/(b/l));
ans+=(sg[r]-sg[l-1])*1LL*(a/l)*1LL*(b/l)*1LL;
}
cout<<ans<<endl;
return 0;
}
常数大,代码丑(╯︵╰)****
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ASP.NET Core 模型验证消息的本地化新姿势
· 从零开始开发一个 MCP Server!
· ThreeJs-16智慧城市项目(重磅以及未来发展ai)
· .NET 原生驾驭 AI 新基建实战系列(一):向量数据库的应用与畅想
· Ai满嘴顺口溜,想考研?浪费我几个小时
· Browser-use 详细介绍&使用文档