# bzoj 2301 -莫比乌斯函数反演+分块优化

Description

Input

Output

Sample Input

2 5 1 5 1
1 5 1 5 2

Sample Output

14

HINT

100%的数据满足：1≤n≤50000，1≤a≤b≤50000，1≤c≤d≤50000，1≤k≤50000

7

•首先利用容斥原理将一个询问拆分成四个，每次询问有多少个数对(x,y)满足1<=x<=n,1<=y<=m且gcd(x,y)=k

•这个问题等价于询问有多少个数对(x,y)满足1<=x<=floor(n/k),1<=y<=floor(m/k)且x与y互质

f(x)为1<=i<=n,1<=j<=m且gcd(i,j)=x的数对(i,j)的个数

•F(x)为1<=i<=n,1<=j<=m且 x|gcd(x,y)的数对(i,j)的个数，也就是gcd(i,j)是x的倍数的所有(i,j)的个数

ll solve(ll n,ll m )
{
if (n>m)swap(n,m);
ll ret=0;
for (int i=1,last;i<=n;i=last+1)
{
last=min(n/(n/i),m/(m/i));
ret+=(sum[last]-sum[i-1])*(n/i)*(m/i);
}
return ret;
}

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long  ll;
const ll p =1000000007;
const int  N=50000;
bool is_prime[N+500];
int prime[N+50];
int mu[N+50];
ll sum[N+50];
ll tot;
void Moblus()
{
tot = 0;
mu[1] = 1;
for(ll i = 2; i < N; i++)
{
if(!is_prime[i])
{
prime[tot++] = i;
mu[i] = -1;
}
for(ll j = 0; j < tot && i*prime[j] < N; j++)
{
is_prime[i*prime[j]] = 1;
if(i % prime[j])
{
mu[i*prime[j]] = -mu[i];
}
else
{
mu[i*prime[j]] = 0;
break;
}
}
}
}
//找[1,n],[1,m]内互质的数的对数
ll solve(ll n,ll m )
{
if (n>m)swap(n,m);
ll ret=0;
for (int i=1,last;i<=n;i=last+1)
{
last=min(n/(n/i),m/(m/i));
ret+=(sum[last]-sum[i-1])*(n/i)*(m/i);
}
return ret;
}
int main()
{
Moblus();
for (int i=1;i<N;i++)
sum[i]=sum[i-1]+mu[i];
int t;cin>>t;
while(t--)
{
ll k,a,b,c,d;
scanf("%lld",&a);
scanf("%lld",&b);
scanf("%lld",&c);
scanf("%lld",&d);
scanf("%lld",&k);
ll ans1=solve(b/k,d/k);
ll ans2=solve(b/k,(c-1)/k);
ll ans3=solve((a-1)/k,d/k);
ll ans4=solve((a-1)/k,(c-1)/k);

printf("%lld\n",ans1-ans2-ans3+ans4);
}

return 0;
}


------------------

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客