2702. problem b

题目链接

2702. problem b
215. 破译密码

对于给出的 n 个询问,每次求有多少个数对 (x,y),满足 axbcyd,且 gcd(x,y)=kgcd(x,y) 函数为 xy 的最大公约数。

输入格式

第一行一个整数 n

接下来 n 行每行五个整数,分别表示 abcdk

输出格式

n 行,每行一个整数表示满足要求的数对 (x,y) 的个数。

数据范围

1n50000,
1ab50000,
1cd50000,
1k50000

输入样例:

2 2 5 1 5 1 1 5 1 5 2

输出样例:

14 3

解题思路

莫比乌斯反演

本题单用容斥原理和莫比乌斯函数也可做:215. 破译密码

这里介绍莫比乌斯反演做法

先给出莫比乌斯函数的一个性质:dnμ(d)={1n=10n1 。简略证明:n=1 时显然。当 n>1 时,对 n 分解质因数:n=i=1kpici,当存在 ci>1 时该项表示的约数的 dμ(d)=0,这种情况的约数不考虑,即只用考虑 i=1kpi 的约数,即在这 k 个数中选出 1 个数组成约数,2 组成约数,3 个数组成约数,,组成 k 个数组成约数,由莫比乌斯函数,奇数种质数为 1,偶数种质数为 1,则 dnμ(d)=i=0kCki(1)i=(1+(1))k=0
接着,有莫比乌斯反演的两条重要定理:

  1. 如果有 F(n)=dnf(d) ,那么有 f(n)=dnμ(d)F(nd)
    证明:F(n)=dnf(d) 代入,得 dnμ(d)indf[i],观察 id 配对的情况,当 d=1i 取遍 n 的约数,而对于某个固定的 i,要求找出与 i 配对的 d,这样的 d 需满足:dn,ind,即 dni,此时可以交换 i,d 顺序,即:inf(i)dniμ(d),由莫比乌斯函数约数和性质,当且仅当 i=n 时后面的和不为 0,即inf(i)dniμ(d)=f(n)

  2. 如果有 F(n)=ndf(d) ,那么有 f(n)=ndμ(dn)F(d)
    同理。这条定理常用。

本题按前缀和可转化为求解:i=1aj=1b[(i,j)=n],其中 (i,j) 表示 ij 的最大公约数

由莫比乌斯反演的性质,求解 F(n) 容易,求解 f(n) 困难,本题中 f(n)=i=1aj=1b[(i,j)=n],而由莫比乌斯反演第二条定理,可设定 F(n)=i=1aj=1b[n(i,j)],其含义表示的是 x[1,a],y[1,b]gcd(x,y)n 的倍数的点数,[1,a] 中有 a/n 个值是 n 的倍数,[1,b] 中有 b/n 个值是 n 的倍数,由乘法原理,共有 (a/n)×(b/n) 个点满足要求,即 F(n)=(a/n)×(b/n),则 f(n)=ndμ(dn)(a/d)×(b/d),令 d=dn,则 f(n)=dμ(d)(a/dn)×(b/dn),而倍数 d 也不能无限大,(d)(a/dn)×(b/dn) 导致 d 最大为 n=min(a/n,b/n),令 a=a/n,b=b/n,即 f(n)=i=1nμ(i)(a/i)×(b/i),此时转化为单靠容斥原理得到的结论

  • 时间复杂度:(nn)

代码

// Problem: problem b // Contest: AcWing // URL: https://www.acwing.com/problem/content/2704/ // Memory Limit: 64 MB // Time Limit: 3000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } const int N=5e4+5; int q,a,b,c,d,k,m,prime[N],v[N],u[N],s[N]; void primes(int n) { u[1]=1; for(int i=2;i<=n;i++) { if(v[i]==0) { u[i]=-1; v[i]=prime[++m]=i; } for(int j=1;prime[j]*i<=n&&j<=m;j++) { if(v[i]<prime[j])break; if(i%prime[j]==0) u[i*prime[j]]=0; else u[i*prime[j]]=-u[i]; v[i*prime[j]]=prime[j]; } } for(int i=1;i<=n;i++)s[i]=s[i-1]+u[i]; } int g(int a,int b) { return a/(a/b); } LL f(int a,int b,int d) { LL res=0; a/=d,b/=d; int n=min(a,b); for(int l=1,r;l<=n;l=r+1) { r=min({n,g(a,l),g(b,l)}); res+=1ll*(s[r]-s[l-1])*(a/l)*(b/l); } return res; } int main() { primes(N-1); cin>>q; while(q--) { cin>>a>>b>>c>>d>>k; cout<<f(b,d,k)-f(b,c-1,k)-f(a-1,d,k)+f(a-1,c-1,k)<<'\n'; } return 0; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/16421846.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示