先带这个玩意儿
https://www.cnblogs.com/lcchuguo/p/5061692.html
第一次接触这么高端的玩意儿。
给定5个整数a,b,c,d,e,在
[a,b]
[
a
,
b
]
区间找一个数
x
x
,在找一个
y
y
,使得 ,问
(x,y)
(
x
,
y
)
这样的对数
思路
思
路
组合数学问题
那个 莫比乌斯函数我不太清楚原理qwq,两个方法求之,一个
ο(n)
ο
(
n
)
一个
ο(n∗log(n))
ο
(
n
∗
log
(
n
)
)
莫比乌斯反演链接:
https://www.cnblogs.com/Milkor/p/4464515.html
理论篇
理
论
篇
https://blog.csdn.net/lixuepeng_001/article/details/50577932
参考来源
参
考
来
源
https://blog.csdn.net/litble/article/details/72804050
优秀博客1
优
秀
博
客
1
https://blog.csdn.net/hnust_taoshiqian/article/details/47282203
优秀博客2
优
秀
博
客
2
两种求法:
这里F(X)为挑选数目为有多少对满足
gcd(x,y)==e的倍数
g
c
d
(
x
,
y
)
==
e
的
倍
数
。
并且 F(x)满足第二张图片
(即F(n)为gcd为n的倍数的对数,这个答案等于所有f(d)的和,d为n的倍数,即gcd是n的1倍,2倍,3倍的累加和。)
(
即
F
(
n
)
为
g
c
d
为
n
的
倍
数
的
对
数
,
这
个
答
案
等
于
所
有
f
(
d
)
的
和
,
d
为
n
的
倍
数
,
即
g
c
d
是
n
的
1
倍
,
2
倍
,
3
倍
的
累
加
和
。
)
不太懂这个就感觉比较神奇。然后就可以用第二张图片来计算了。
注意有一个小trick,该答案中x和y相同的只能计算一次,于是计算一下x和y的min的范围,在这个范围内(x,y)和(y,x)都会计算一遍,所以我们直接减去就行。(当然存在更多的比较笨的计算方法啦!)
慢慢学习吧!
ps:用容斥什么的可以慢慢写?
#include <bits/stdc++.h>
typedef long long LL;
using namespace std;
/* 求莫比乌斯函数就是那个不知道有啥用的函数。
那个函数有俩性质。()
**************************
根据莫比乌斯反演可以通过F(n)来计算f(n)
或者通过 f(n)来计算F(n)。
这两个都是 算术函数(定义域为所有正整数的函数)
*/
const int MAXN = 100000;
/*//线性筛法求莫比乌斯函数
bool check[MAXN+10];
int prime[MAXN+10];
int mu[MAXN+10];
void Moblus()
{
memset(check,false,sizeof(check));
mu[1] = 1;
int tot = 0;
for(int i = 2; i <= MAXN; i++)
{
if( !check[i] )
{
prime[tot++] = i;
mu[i] = -1;
}
for(int j = 0; j < tot; j++)
{
if(i * prime[j] > MAXN) break;
check[i * prime[j]] = true;
if( i % prime[j] == 0)
{
mu[i * prime[j]] = 0;
break;
}
else
{
mu[i * prime[j]] = -mu[i];
}
}
}
}
*/
int mu[MAXN+10]={0};
void getMu(){//n*logn
for(int i=1; i<=MAXN; i++)
{
int target = i==1?1:0;
int delta = target - mu[i];
mu[i]=delta;
for(int j=i*2; j<=MAXN; j+=i)
mu[j]+=delta;
}
}
int main()
{ int t;
int a,b,c,d,e;
getMu();
int tim=1;
scanf("%d",&t);
while(t--){
scanf("%d%d%d%d%d",&a,&b,&c,&d,&e);
if(!e){
printf("Case %d: 0\n",tim++);
continue;
}
b/=e;
d/=e;
long long ans=0;
long long rel=0;
if(b>d)swap(b,d);
for(int i=1;i<=min(d,b);i++){
ans+=1ll*mu[i]*(d/i)*(b/i);//用F_x来推断f_x
rel+=1ll*mu[i]*(b/i)*(b/i);
}
printf("Case %d: %lld\n",tim++,ans-rel/2);
}
return 0;
}