莫比乌斯函数及其应用
文章目录
一、莫比乌斯函数
1、定义
μ 为 莫 比 乌 斯 函 数 , 定 义 为 : \mu为莫比乌斯函数,定义为: μ为莫比乌斯函数,定义为:
μ ( n ) = { 1 n = 1 0 n 含 有 平 方 因 子 ( − 1 ) k k 为 n 的 本 质 不 同 质 因 子 个 数 \mu(n)=\begin{cases}1\qquad\qquad n=1\\0\qquad\qquad n含有平方因子\\(-1)^k\qquad k为n的本质不同质因子个数\end{cases} μ(n)=⎩⎪⎨⎪⎧1n=10n含有平方因子(−1)kk为n的本质不同质因子个数
说 明 : 说明: 说明:
记 n = ∏ i = 1 k p i c i , 其 中 p i 为 质 因 子 , c i ≥ 1 。 上 述 定 义 表 示 : 记n=\prod_{i=1}^kp_i^{c_i},其中p_i为质因子,c_i\ge 1。上述定义表示: 记n=∏i=1kpici,其中pi为质因子,ci≥1。上述定义表示:
① 、 n = 1 时 , μ ( n ) = 1 ; ①、n=1时,\mu(n)=1; ①、n=1时,μ(n)=1;
② 、 当 n ≠ 1 时 : ②、当n\ne1时: ②、当n=1时:
a . 若 存 在 i ∈ [ 1 , k ] , 使 得 c i > 1 , μ ( n ) = 0 , 即 若 某 个 质 因 子 次 数 大 于 0 , μ ( n ) 就 等 于 0 。 \qquad a.若存在i∈[1,k],使得c_i>1,\mu(n)=0,即若某个质因子次数大于0,\mu(n)就等于0。 a.若存在i∈[1,k],使得ci>1,μ(n)=0,即若某个质因子次数大于0,μ(n)就等于0。
b . 若 任 意 i ∈ [ 1 , k ] , 都 有 c i = 1 , μ ( n ) = ( − 1 ) k , 即 若 每 个 质 因 子 都 仅 出 现 过 一 次 , μ ( n ) 等 于 − 1 的 k 次 幂 , k 为 不 同 质 因 子 的 个 数 。 \qquad b.若任意i∈[1,k],都有c_i=1,\mu(n)=(-1)^k,即若每个质因子都仅出现过一次,\\\qquad\quad \mu(n)等于-1的k次幂,k为不同质因子的个数。 b.若任意i∈[1,k],都有ci=1,μ(n)=(−1)k,即若每个质因子都仅出现过一次,μ(n)等于−1的k次幂,k为不同质因子的个数。
2、应用
莫 比 乌 斯 函 数 可 用 于 解 决 如 下 问 题 : 莫比乌斯函数可用于解决如下问题: 莫比乌斯函数可用于解决如下问题:
计 算 [ 1 , N ] 中 与 N 互 质 的 数 的 个 数 。 我 们 记 S i 表 示 [ 1 , N ] 中 , 是 i 的 倍 数 的 数 的 个 数 。 计算[1,N]中与N互质的数的个数。我们记S_i表示[1,N]中,是i的倍数的数的个数。 计算[1,N]中与N互质的数的个数。我们记Si表示[1,N]中,是i的倍数的数的个数。
则 答 案 为 : N − S 2 − S 3 − . . . + S 2 , 3 + S 2 , 5 + . . . − S 2 , 3 , 5 − S 2 , 3 , 7 − . . . + . . . 则答案为:N-S_2-S_3-...+S_{2,3}+S_{2,5}+...-S_{2,3,5}-S_{2,3,7}-...+... 则答案为:N−S2−S3−...+S2,3+S2,5+...−S2,3,5−S2,3,7−...+...
即 : N − ⌊ N 2 ⌋ − ⌊ N 3 ⌋ − . . . + ⌊ N 2 ⋅ 3 ⌋ + ⌊ N 2 ⋅ 5 ⌋ + . . . − ⌊ N 2 ⋅ 3 ⋅ 5 ⌋ − ⌊ N 2 ⋅ 3 ⋅ 7 ⌋ − . . . + . . . 即:N-\lfloor\frac{N}{2}\rfloor-\lfloor\frac{N}{3}\rfloor-...+\lfloor\frac{N}{2·3}\rfloor+\lfloor\frac{N}{2·5}\rfloor+...-\lfloor\frac{N}{2·3·5}\rfloor-\lfloor\frac{N}{2·3·7}\rfloor-...+... 即:N−⌊2N⌋−⌊3N⌋−...+⌊2⋅3N⌋+⌊2⋅5N⌋+...−⌊2⋅3⋅5N⌋−⌊2⋅3⋅7N⌋−...+...
这 里 , S i 前 面 的 系 数 就 是 莫 比 乌 斯 函 数 的 第 i 项 μ ( i ) 。 这里,S_i前面的系数就是莫比乌斯函数的第i项\mu(i)。 这里,Si前面的系数就是莫比乌斯函数的第i项μ(i)。
3、莫比乌斯反演定理
定理:
F
(
n
)
和
f
(
n
)
是
定
义
在
非
负
整
数
集
合
上
的
两
个
函
数
,
并
且
满
足
条
件
:
F(n)和f(n)是定义在非负整数集合上的两个函数,并且满足条件:
F(n)和f(n)是定义在非负整数集合上的两个函数,并且满足条件:
F
(
n
)
=
∑
d
∣
n
f
(
d
)
F(n)=\sum_{d|n}f(d)
F(n)=d∣n∑f(d)
那 么 有 : 那么有: 那么有:
f ( n ) = ∑ d ∣ n μ ( d ) F ( ⌊ n d ⌋ ) ( 1 ) f(n)=\sum_{d|n}\mu(d)F(\lfloor\frac{n}{d}\rfloor)\qquad\qquad(1) f(n)=d∣n∑μ(d)F(⌊dn⌋)(1)
或 者 : 或者: 或者:
f ( n ) = ∑ n ∣ d μ ( ⌊ d n ⌋ ) F ( d ) ( 2 ) f(n)=\sum_{n|d}\mu(\lfloor\frac{d}{n}\rfloor)F(d)\qquad\qquad(2) f(n)=n∣d∑μ(⌊nd⌋)F(d)(2)
利 用 性 质 : ∑ d ∣ n μ ( d ) = { 1 n = 1 0 n = 0 , 容 易 证 明 。 利用性质:\sum_{d|n}\mu(d)=\begin{cases}1\qquad n=1\\0\qquad n=0\end{cases},容易证明。 利用性质:∑d∣nμ(d)={1n=10n=0,容易证明。
该定理的作用:
对 于 一 些 函 数 f ( n ) , 如 果 我 们 很 难 直 接 求 出 它 的 值 , 而 容 易 求 出 对于一些函数f(n),如果我们很难直接求出它的值,而容易求出 对于一些函数f(n),如果我们很难直接求出它的值,而容易求出倍数和(式2) 或 或 或约数和(式1) F ( n ) , 那 么 我 们 可 以 通 过 莫 比 乌 斯 反 演 来 求 得 f ( n ) 的 值 。 F(n),那么我们可以通过莫比乌斯反演来求得f(n)的值。 F(n),那么我们可以通过莫比乌斯反演来求得f(n)的值。
例 : f ( n ) 表 示 某 一 范 围 内 ( x , y ) = n 的 数 对 的 数 量 , F ( n ) 表 示 某 一 范 围 内 n ∣ ( x , y ) 的 数 对 的 数 量 。 例:f(n)表示某一范围内(x,y)=n的数对的数量,F(n)表示某一范围内n|(x,y)的数对的数量。 例:f(n)表示某一范围内(x,y)=n的数对的数量,F(n)表示某一范围内n∣(x,y)的数对的数量。
当 f ( n ) 不 好 求 时 , 我 们 可 以 通 过 对 F ( n ) 反 演 求 f ( n ) 。 当f(n)不好求时,我们可以通过对F(n)反演求f(n)。 当f(n)不好求时,我们可以通过对F(n)反演求f(n)。
二、例题
1、P3455 [POI2007] ZAP-Queries
题意:
对于给定的整数a,b和d,有多少正整数对x,y,满足x≤a,y≤b,并且gcd(x,y)=d。
输入格式
第一行包含一个正整数n,表示一共有n组询问。
接下来n行,每行表示一个询问,每行三个正整数,分别为a,b,d。
输出格式
对于每组询问,输出一个正整数,表示满足条件的整数对数。
数据范围
1≤n≤50000,
1≤d≤a,b≤50000
输入样例:
2
4 5 2
6 4 3
输出样例:
3
2
分析:
1 ≤ x ≤ a , 1 ≤ y ≤ b , 使 得 g c d ( x , y ) = d 1\le x\le a,1\le y\le b,使得gcd(x,y)=d 1≤x≤a,1≤y≤b,使得gcd(x,y)=d
等 价 于 : 等价于: 等价于:
1 ≤ x ′ ≤ ⌊ a d ⌋ , 1 ≤ y ′ ≤ ⌊ b d ⌋ , 使 得 g c d ( x ′ , y ′ ) = 1 1\le x'\le \lfloor\frac{a}{d}\rfloor,1\le y'\le \lfloor\frac{b}{d}\rfloor,使得gcd(x',y')=1 1≤x′≤⌊da⌋,1≤y′≤⌊db⌋,使得gcd(x′,y′)=1
我 们 的 问 题 转 化 为 : 计 算 满 足 1 ≤ x ′ ≤ ⌊ a d ⌋ , 1 ≤ y ′ ≤ ⌊ b d ⌋ , 互 质 的 数 对 的 数 量 。 我们的问题转化为:计算满足1\le x'\le \lfloor\frac{a}{d}\rfloor,1\le y'\le \lfloor\frac{b}{d}\rfloor,互质的数对的数量。 我们的问题转化为:计算满足1≤x′≤⌊da⌋,1≤y′≤⌊db⌋,互质的数对的数量。
答 案 应 当 是 : 总 方 案 数 − 不 合 法 方 案 数 = 总 方 案 数 − 有 公 因 子 2 的 方 案 数 − 有 公 因 子 3 的 方 案 数 − . . . + 有 公 因 子 2 和 3 的 方 案 数 + 有 公 因 子 2 和 5 的 方 案 数 + . . . − 有 公 因 子 2 、 3 、 5 的 方 案 数 − 有 公 因 子 2 、 3 、 7 的 方 案 总 数 − . . . . . . 答案应当是:总方案数-不合法方案数\\=总方案数-有公因子2的方案数-有公因子3的方案数-...\\+有公因子2和3的方案数+有公因子2和5的方案数+...\\-有公因子2、3、5的方案数-有公因子2、3、7的方案总数-...\\... 答案应当是:总方案数−不合法方案数=总方案数−有公因子2的方案数−有公因子3的方案数−...+有公因子2和3的方案数+有公因子2和5的方案数+...−有公因子2、3、5的方案数−有公因子2、3、7的方案总数−......
方 案 总 数 : a ′ ⋅ b ′ 方案总数:a'·b' 方案总数:a′⋅b′
只 有 有 一 个 公 因 子 p i 的 方 案 总 数 : 区 间 [ 1 , a ′ ] 中 , p i 的 倍 数 的 个 数 ⌊ a ′ p i ⌋ , 区 间 [ 1 , b ′ ] 中 , p i 的 倍 数 的 个 数 ⌊ b ′ p i ⌋ , 那 么 总 的 方 案 数 为 ⌊ a ′ p i ⌋ ⋅ ⌊ b ′ p i ⌋ 只有有一个公因子p_i的方案总数:区间[1,a']中,p_i的倍数的个数\lfloor\frac{a'}{p_i}\rfloor,\\\qquad\qquad\qquad\qquad\qquad\qquad\qquad\ \ \ 区间[1,b']中,p_i的倍数的个数\lfloor\frac{b'}{p_i}\rfloor,\\\qquad\qquad\qquad\qquad\qquad\qquad\qquad\ \ \ 那么总的方案数为\lfloor\frac{a'}{p_i}\rfloor·\lfloor\frac{b'}{p_i}\rfloor 只有有一个公因子pi的方案总数:区间[1,a′]中,pi的倍数的个数⌊pia′⌋, 区间[1,b′]中,pi的倍数的个数⌊pib′⌋, 那么总的方案数为⌊pia′⌋⋅⌊pib′⌋
有 多 个 公 因 子 的 方 案 总 数 的 计 算 同 上 。 有多个公因子的方案总数的计算同上。 有多个公因子的方案总数的计算同上。
答 案 即 : 答案即: 答案即:
a ′ b ′ − ⌊ a ′ 2 ⌋ ⌊ b ′ 2 ⌋ − ⌊ a ′ 3 ⌋ ⌊ b ′ 3 ⌋ − . . . + ⌊ a ′ 2 ⋅ 3 ⌋ ⌊ b ′ 2 ⋅ 3 ⌋ + ⌊ a ′ 2 ⋅ 5 ⌋ ⌊ b ′ 2 ⋅ 5 ⌋ + . . . − ⌊ a ′ 2 ⋅ 3 ⋅ 5 ⌋ ⌊ b ′ 2 ⋅ 3 ⋅ 5 ⌋ − ⌊ a ′ 2 ⋅ 3 ⋅ 7 ⌋ ⌊ b ′ 2 ⋅ 3 ⋅ 7 ⌋ − . . . + . . . a'b'-\lfloor\frac{a'}{2}\rfloor\lfloor\frac{b'}{2}\rfloor-\lfloor\frac{a'}{3}\rfloor\lfloor\frac{b'}{3}\rfloor-...+\lfloor\frac{a'}{2·3}\rfloor\lfloor\frac{b'}{2·3}\rfloor+\lfloor\frac{a'}{2·5}\rfloor\lfloor\frac{b'}{2·5}\rfloor+...\\\ \\-\lfloor\frac{a'}{2·3·5}\rfloor\lfloor\frac{b'}{2·3·5}\rfloor-\lfloor\frac{a'}{2·3·7}\rfloor\lfloor\frac{b'}{2·3·7}\rfloor-...+... a′b′−⌊2a′⌋⌊2b′⌋−⌊3a′⌋⌊3b′⌋−...+⌊2⋅3a′⌋⌊2⋅3b′⌋+⌊2⋅5a′⌋⌊2⋅5b′⌋+... −⌊2⋅3⋅5a′⌋⌊2⋅3⋅5b′⌋−⌊2⋅3⋅7a′⌋⌊2⋅3⋅7b′⌋−...+...
能 够 发 现 , 上 式 等 价 于 : 能够发现,上式等价于: 能够发现,上式等价于:
∑ i = 1 m i n ( a ′ , b ′ ) ⌊ a ′ i ⌋ ⋅ ⌊ b ′ i ⌋ ⋅ μ ( i ) \sum_{i=1}^{min(a',b')}\lfloor\frac{a'}{i}\rfloor·\lfloor\frac{b'}{i}\rfloor·\mu(i) i=1∑min(a′,b′)⌊ia′⌋⋅⌊ib′⌋⋅μ(i)
检 验 : 当 分 母 的 k 个 质 因 子 的 次 数 都 为 1 , 系 数 为 ( − 1 ) k 。 当 分 母 的 某 个 质 因 子 次 数 大 于 1 , 系 数 为 0 。 检验:当分母的k个质因子的次数都为1,系数为(-1)^k。\\\qquad\quad当分母的某个质因子次数大于1,系数为0。 检验:当分母的k个质因子的次数都为1,系数为(−1)k。当分母的某个质因子次数大于1,系数为0。
观 察 这 个 式 子 , 前 一 半 我 们 可 以 通 过 整 除 分 块 , 将 时 间 复 杂 度 降 到 O ( n ) ; 观察这个式子,前一半我们可以通过整除分块,将时间复杂度降到O(\sqrt{n}); 观察这个式子,前一半我们可以通过整除分块,将时间复杂度降到O(n);
后 一 半 借 助 前 缀 和 来 计 算 每 一 块 的 ∑ μ ( i ) 。 后一半借助前缀和来计算每一块的\sum\mu(i)。 后一半借助前缀和来计算每一块的∑μ(i)。
从莫比乌斯反演的角度来看待这个问题:
f ( k ) = ∑ 1 ≤ x ≤ a , 1 ≤ y ≤ b [ g c d ( x , y ) = = k ] f(k)=\sum_{1\le x\le a,1\le y\le b}[gcd(x,y)==k] f(k)=1≤x≤a,1≤y≤b∑[gcd(x,y)==k]
记 F ( i ) 为 1 ≤ x ≤ a , 1 ≤ y ≤ b 且 i ∣ g c d ( x , y ) 的 数 对 ( x , y ) 的 个 数 记F(i)为1\le x\le a, 1\le y\le b且i\ |\ gcd(x,y )的数对(x,y)的个数 记F(i)为1≤x≤a,1≤y≤b且i ∣ gcd(x,y)的数对(x,y)的个数
即 F ( i ) 是 区 间 x ∈ [ 1 , a ] , y ∈ [ 1 , b ] 上 , 满 足 g c d ( x , y ) 是 i 的 倍 数 的 数 对 的 个 数 : 即F(i)是区间x∈[1,a],y∈[1,b]上,满足gcd(x,y)是i的倍数的数对的个数: 即F(i)是区间x∈[1,a],y∈[1,b]上,满足gcd(x,y)是i的倍数的数对的个数:
F ( i ) = ∑ i ∣ d f ( d ) = ⌊ a i ⌋ ⋅ ⌊ b i ⌋ F(i)=\sum_{i|d}f(d)=\lfloor\frac{a}{i}\rfloor·\lfloor\frac{b}{i}\rfloor F(i)=i∣d∑f(d)=⌊ia⌋⋅⌊ib⌋
利 用 反 演 定 理 , 有 : 利用反演定理,有: 利用反演定理,有:
f ( i ) = ∑ i ∣ d μ ( d i ) F ( d ) = ∑ i ∣ d μ ( d i ) ⌊ a d ⌋ ⌊ b d ⌋ f(i)=\sum_{i|d}\mu(\frac{d}{i})F(d)=\sum_{i|d}\mu(\frac{d}{i})\lfloor\frac{a}{d}\rfloor\lfloor\frac{b}{d}\rfloor f(i)=i∣d∑μ(id)F(d)=i∣d∑μ(id)⌊da⌋⌊db⌋
则 : f ( k ) = ∑ k ∣ d μ ( d k ) F ( d ) = ∑ k ∣ d μ ( d k ) ⋅ ⌊ a d ⌋ ⋅ ⌊ b d ⌋ = ∑ j = 1 m i n ( a k , b k ) μ ( j ) ⋅ ( ⌊ a k ⌋ / j ) ⋅ ( ⌊ b k ⌋ / j ) 则:f(k)=\sum_{k|d}\mu(\frac{d}{k})F(d)=\sum_{k|d}\mu(\frac{d}{k})·\lfloor\frac{a}{d}\rfloor·\lfloor\frac{b}{d}\rfloor=\sum_{j=1}^{min(\frac{a}{k},\frac{b}{k})}\mu(j)·(\lfloor\frac{a}{k}\rfloor/j)·(\lfloor\frac{b}{k}\rfloor/j) 则:f(k)=k∣d∑μ(kd)F(d)=k∣d∑μ(kd)⋅⌊da⌋⋅⌊db⌋=j=1∑min(ka,kb)μ(j)⋅(⌊ka⌋/j)⋅(⌊kb⌋/j)
然 后 我 们 枚 举 k 的 所 有 倍 数 d , 就 能 够 计 算 得 到 f ( k ) 然后我们枚举k的所有倍数d,就能够计算得到f(k) 然后我们枚举k的所有倍数d,就能够计算得到f(k)
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int N = 50010;
int T, a, b, d;
int mu[N], primes[N], cnt, sum[N];
bool st[N];
void get_prime(int n)
{
mu[1]=1;
for(int i=2;i<=n;i++)
{
if(!st[i])
{
primes[cnt++]=i;
mu[i]=-1;
}
for(int j=0;primes[j]*i<=n;j++)
{
st[primes[j]*i]=true;
if(i%primes[j]==0)
{
mu[i*primes[j]]=0;
break;
}
mu[i*primes[j]]=mu[i]*-1;
}
}
for(int i=1;i<=n;i++) sum[i]=sum[i-1]+mu[i];
}
int main()
{
get_prime(N-1);
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&a,&b,&d);
a/=d, b/=d;
int n=min(a,b);
ll res=0;
for(int i=1, r=1;i<=n;i=r+1)
{
r=min(a/(a/i), b/(b/i));
r=min(r,n);
res+=(sum[r]-sum[i-1])*(ll)(a/i)*(b/i);
}
printf("%lld\n",res);
}
return 0;
}
2、P2522 [HAOI2011] Problem b
题目描述
对于给出的 n 个询问,每次求有多少个数对 (x,y),满足 a≤x≤b,c≤y≤d,且 gcd(x,y)=k,gcd(x,y) 函数为 x 和 y 的最大公约数。
输入格式
第一行一个整数 n,接下来 n 行每行五个整数,分别表示 a,b,c,d,k。
输出格式
共 n 行,每行一个整数表示满足要求的数对 (x,y) 的个数。
输入输出样例
输入
2
2 5 1 5 1
1 5 1 5 2
输出
14
3
说明/提示
对于 100% 的数据满足:
1
≤
n
,
k
≤
5
×
1
0
4
1≤n,k≤5×10^4
1≤n,k≤5×104 ,
1
≤
a
≤
b
≤
5
×
1
0
4
1≤a≤b≤5×10^4
1≤a≤b≤5×104,
1
≤
c
≤
d
≤
5
×
1
0
4
1≤c≤d≤5×10 ^4
1≤c≤d≤5×104。
分析:
记 a ′ = a k , b ′ = b k , c ′ = c k , d ′ = d k 记a'=\frac{a}{k},b'=\frac{b}{k},c'=\frac{c}{k},d'=\frac{d}{k} 记a′=ka,b′=kb,c′=kc,d′=kd
本 题 等 价 于 计 算 : 本题等价于计算: 本题等价于计算:
区 间 [ a ′ , b ′ ] 和 区 间 [ c ′ , d ′ ] 中 , 互 质 的 数 对 的 个 数 。 区间[a',b']和区间[c',d']中,互质的数对的个数。 区间[a′,b′]和区间[c′,d′]中,互质的数对的个数。
我们可以借助前缀和和容斥的思想,来做一个巧妙的转化:
分 为 4 个 部 分 : 分为4个部分: 分为4个部分:
先 计 算 出 区 间 [ 1 , b ′ ] 和 区 间 [ 1 , d ′ ] 中 互 质 的 数 对 的 个 数 C 1 先计算出区间[1,b']和区间[1,d']中互质的数对的个数C_1 先计算出区间[1,b′]和区间[1,d′]中互质的数对的个数C1
再 计 算 出 区 间 [ 1 , a ′ − 1 ] 和 区 间 [ 1 , d ′ ] 互 质 的 数 对 的 个 数 C 2 , 区 间 [ 1 , b ′ ] 和 区 间 [ 1 , c ′ − 1 ] 互 质 的 数 对 个 数 C 3 再计算出区间[1,a'-1]和区间[1,d']互质的数对的个数C_2,区间[1,b']和区间[1,c'-1]互质的数对个数C_3 再计算出区间[1,a′−1]和区间[1,d′]互质的数对的个数C2,区间[1,b′]和区间[1,c′−1]互质的数对个数C3
区 间 [ 1 , a ′ − 1 ] 和 区 间 [ 1 , c ′ − 1 ] 互 质 的 数 对 个 数 C 4 区间[1,a'-1]和区间[1,c'-1]互质的数对个数C_4 区间[1,a′−1]和区间[1,c′−1]互质的数对个数C4
则 答 案 为 : 则答案为: 则答案为:
C 1 − C 2 − C 3 + C 4 C_1-C_2-C_3+C_4 C1−C2−C3+C4
而 上 面 每 一 部 分 , 我 们 都 可 以 借 助 例 题 1 中 的 方 法 来 解 决 。 而上面每一部分,我们都可以借助例题1中的方法来解决。 而上面每一部分,我们都可以借助例题1中的方法来解决。
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int N = 50010;
int T, a, b, c, d, k;
int mu[N], primes[N], cnt, sum[N];
bool st[N];
void get_prime(int n)
{
mu[1]=1;
for(int i=2;i<=n;i++)
{
if(!st[i])
{
primes[cnt++]=i;
mu[i]=-1;
}
for(int j=0;primes[j]*i<=n;j++)
{
st[primes[j]*i]=true;
if(i%primes[j]==0)
{
mu[i*primes[j]]=0;
break;
}
mu[i*primes[j]]=mu[i]*-1;
}
}
for(int i=1;i<=n;i++) sum[i]=sum[i-1]+mu[i];
}
ll cal(int a,int b) //计算区间[1,a]和区间[1,b]中gcd(x,y)=k的数对数量
{
a/=k, b/=k;
int n=min(a,b);
ll res=0;
for(int i=1, r=1;i<=n;i=r+1)
{
r=min(a/(a/i), b/(b/i));
r=min(r,n);
res+=(ll)(sum[r]-sum[i-1])*(a/i)*(b/i);
}
return res;
}
int main()
{
get_prime(N-1);
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
printf("%lld\n",cal(b,d) - cal(a-1,d) - cal(b,c-1) + cal(a-1,c-1));
}
return 0;
}
3、GCD - HDU 1695
题意:
给出a,b,c,d,k,求出a<=x<=b, c<=y<=d 且gcd(x,y) == k 的(x,y)的对数,其中gcd(x,y)和gcd(y,x)被认为是同一种,应当舍去。
Input
样例个数T (T <= 3000) 每个样例输入a,b,c,d,k,保证所有的a和c都等于1. (a=1 , c=1 , 0 < b,d <= 100,000 , 0 <= k <= 100,000)
Output
对于每个样例,输出其对应的答案。
Sample Input
2
1 3 1 5 1
1 11014 1 14409 9
Sample Output
Case 1: 9
Case 2: 736427
分析:
要 考 虑 重 复 的 情 况 , 对 于 区 间 [ 1 , b ] 和 区 间 [ 1 , d ] , 假 设 b < d , 的 情 况 。 要考虑重复的情况,对于区间[1,b]和区间[1,d],假设b<d,的情况。 要考虑重复的情况,对于区间[1,b]和区间[1,d],假设b<d,的情况。
重 复 的 方 案 数 应 当 是 [ 1 , b ] 与 [ 1 , b ] 的 方 案 总 数 的 一 半 。 重复的方案数应当是[1,b]与[1,b]的方案总数的一半。 重复的方案数应当是[1,b]与[1,b]的方案总数的一半。
因 此 我 们 计 算 出 区 间 [ 1 , b ] 和 区 间 [ 1 , d ] 的 g c d ( x , y ) = k 的 对 数 c a l ( b , d ) , 再 减 去 重 复 的 方 案 数 c a l ( b , b ) 2 因此我们计算出区间[1,b]和区间[1,d]的gcd(x,y)=k的对数cal(b,d),再减去重复的方案数\frac{cal(b,b)}{2} 因此我们计算出区间[1,b]和区间[1,d]的gcd(x,y)=k的对数cal(b,d),再减去重复的方案数2cal(b,b)
本题需要注意: k 可 能 为 0. k可能为0. k可能为0.
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int N = 100010;
int T, a, b, c, d, k;
int mu[N], primes[N], cnt, sum[N];
bool st[N];
void get_prime(int n)
{
mu[1]=1;
for(int i=2;i<=n;i++)
{
if(!st[i])
{
primes[cnt++]=i;
mu[i]=-1;
}
for(int j=0;primes[j]*i<=n;j++)
{
st[primes[j]*i]=true;
if(i%primes[j]==0)
{
mu[i*primes[j]]=0;
break;
}
mu[i*primes[j]]=mu[i]*-1;
}
}
for(int i=1;i<=n;i++) sum[i]=sum[i-1]+mu[i];
}
ll cal(int a,int b) //计算区间[1,a]和区间[1,b]中gcd(x,y)=k的数对数量
{
a/=k, b/=k;
int n=min(a,b);
ll res=0;
for(int i=1, r=1;i<=n;i=r+1)
{
r=min(a/(a/i), b/(b/i));
r=min(r,n);
res+=(ll)(sum[r]-sum[i-1])*(a/i)*(b/i);
}
return res;
}
int main()
{
get_prime(N-1);
scanf("%d",&T);
for(int i=1;i<=T;i++)
{
scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
printf("Case %d: ",i);
if(k==0) puts("0");
else printf("%lld\n",cal(b,d)-cal(min(b,d),min(b,d))/2);
}
return 0;
}