hdu1695-GCD-莫比烏斯反演入門
阿新 • • 發佈:2018-12-24
這裡F(X)為挑選數目為有多少對滿足 。
並且 F(x)滿足第二張圖片
不太懂這個就感覺比較神奇。然後就可以用第二張圖片來計算了。
注意有一個小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;
}