hdu1695
Meaning of the questions beg:
Ideas: see gcd sum equation basically Mobius inversion.
Then we divided the original type k, it becomes ,
We set f [k] = (gcd (i, j) = k), F [x] = (k | gcd (i, j)). Then we find ans = f [1]. Easy to get F [k] = (n / i) * (m / k)
Using a second formula, inversion Mobius
and so
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll mod=1e9+7;
const ll maxn=100010;
ll vis[maxn];
ll prime[maxn];
ll cnt;
ll mu[maxn];
ll sum[maxn];
void init()
{
memset(vis,0,sizeof(vis));
cnt=0;mu[1]=1;
for(ll i=2;i<=maxn;i++)
{
if(!vis[i]) prime[cnt++]=i,mu[i]=-1;
for(ll j=0;j<cnt&&prime[j]*i<=maxn;j++)
{
vis[i*prime[j]]=1;
if(i%prime[j]==0)
{
mu[i*prime[j]]=0;break;
}
else
{
mu[i*prime[j]]=-mu[i];
}
}
}
sum[0]=0;
for(ll i=1;i<maxn;i++) sum[i]=sum[i-1]+mu[i];
}
int main()
{
ll a,b,c,d,k;
init();
ll T;scanf("%lld",&T);ll cas=0;
while(T--)
{
cas++;
scanf("%lld%lld%lld%lld%lld",&a,&b,&c,&d,&k);
cout<<"Case "<<cas<<": ";
if(k==0) cout<<0<<endl;
else
{
b/=k;d/=k;
if(b>d) swap(b,d);
ll ans1=0;ll last=1;
for(ll i=1;i<=min(b,d);i=last+1) //整数分块
{
last=min(b/(b/i),d/(d/i));
ans1+=(sum[last]-sum[i-1])*(b/i)*(d/i);
}
ll ans2=0;
last=1;
for(ll i=1;i<=b;i=last+1) //整数分块
{
last=b/(b/i);
ans2+=(sum[last]-sum[i-1])*(b/i)*(b/i);
}
printf("%lld\n",ans1-ans2/2);
}
}
return 0;
}
bzoj2301
Meaning of the questions above, and a similar problem, seek , note the difference between this question and the question, is no longer the interval from the beginning, and (x, y) and (y, x) for all the answers contribution 1.
Ibid., After inversion requires the inclusion-exclusion. Provided solve (x, y, k) of
The answer is solve (b, d, k) -solve (a-1, d, k) -solve (b, c-1, k) + solve (a-1, c-1, k)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll mod=1e9+7;
const ll maxn=100010;
ll vis[maxn];
ll prime[maxn];
ll cnt;
ll mu[maxn];
ll sum[maxn];
void init()
{
memset(vis,0,sizeof(vis));
cnt=0;mu[1]=1;
for(ll i=2;i<=maxn;i++)
{
if(!vis[i]) prime[cnt++]=i,mu[i]=-1;
for(ll j=0;j<cnt&&prime[j]*i<=maxn;j++)
{
vis[i*prime[j]]=1;
if(i%prime[j]==0)
{
mu[i*prime[j]]=0;break;
}
else
{
mu[i*prime[j]]=-mu[i];
}
}
}
sum[0]=0;
for(ll i=1;i<maxn;i++) sum[i]=sum[i-1]+mu[i];
}
ll solve(ll b, ll d,ll k)
{
b/=k;d/=k;
if(b>d) swap(b,d);
ll ans1=0;
ll last=1;
for(ll i=1;i<=min(b,d);i=last+1) //整数分块
{
last=min(b/(b/i),d/(d/i));
ans1+=(sum[last]-sum[i-1])*(b/i)*(d/i);
}
ll ans2=0;
last=1;
for(ll i=1;i<=b;i=last+1) //整数分块
{
last=b/(b/i);
ans2+=(sum[last]-sum[i-1])*(b/i)*(b/i);
}
return ans1;
}
int main()
{
ll a,b,c,d,k;
init();
ll T;scanf("%lld",&T);ll cas=0;
while(T--)
{
cas++;
scanf("%lld%lld%lld%lld%lld",&a,&b,&c,&d,&k);
if(k==0) cout<<0<<endl;
else
{
ll ans=solve(b,d,k)-solve(a-1,d,k)-solve(b,c-1,k)+solve(a-1,c-1,k);
printf("%lld\n",ans);
}
}
return 0;
}