欢迎大家访问我的老师的OJ———caioj.cn
传送门
这道题和可见点数没有差别。
欧拉函数做法就不写了。
主要讲讲莫反做法吧。
回顾一下Zap(这真的是一道模板题啊!)
设 D ( a , b , k ) D(a,b,k) D(a,b,k)表示满足 x ≤ a , y ≤ b x\le a,y\le b x≤a,y≤b且 k ∣ gcd ( x , y ) k \mid \gcd(x,y) k∣gcd(x,y)的二元组有多少对。
由于 D ( a , b , k ) = ⌊ a / k ⌋ ∗ ⌊ b / k ⌋ D(a,b,k)=\left\lfloor a/k\right\rfloor* \left\lfloor b/k\right\rfloor D(a,b,k)=⌊a/k⌋∗⌊b/k⌋
设 F ( a , b ) F(a,b) F(a,b)表示满足 x ≤ a , y ≤ b x\le a,y\le b x≤a,y≤b并且 x , y x,y x,y互质的二元组有多少对。
由于
F ( a , b ) = ∑ i = 1 min ( a , b ) μ ( i ) ∗ D ( a , b , i ) F(a,b)=\sum_{i=1}^{\operatorname{min}(a,b)}\mu(i)*D(a,b,i) F(a,b)=i=1∑min(a,b)μ(i)∗D(a,b,i)
因为本题要求的是除(1,0),(0,1)两点以外, ∀ x , y ∈ [ 1 , n ] , gcd ( x , y ) = 1 \forall x,y\in[1,n],\gcd(x,y)=1 ∀x,y∈[1,n],gcd(x,y)=1的对数。
F ( n , n ) + 2 F(n,n)+2 F(n,n)+2就为所求。
+ 2 +2 +2是因为 ( 1 , 0 ) , ( 0 , 1 ) (1,0),(0,1) (1,0),(0,1)
#include
#include
#include
#include
#include
#define ll long long
using namespace std;
const int N=4e4+10;
const int M=2e4+10;
int n,m,mu[N],prime[M];bool v[N];
void g_p()
{
memset(v,false,sizeof(v));m=0;mu[1]=1;
for(int i=2;i<=n;i++)
{
if(!v[i])mu[i]=-1,prime[++m]=i;
for(int j=1;j<=m&&i*prime[j]<=n;j++)
{
v[i*prime[j]]=1;
if(i%prime[j]==0){mu[i*prime[j]]=0;break;}
mu[i*prime[j]]=-mu[i];
}
}
for(int i=2;i<=n;i++)mu[i]+=mu[i-1];
}
inline ll calc(int a,int b)
{
if(a>b)swap(a,b);ll ans=0;
for(int x=1,gx;x<=a;x=gx+1)
{
gx=min(a/(a/x),b/(b/x));
ans+=(ll)(mu[gx]-mu[x-1])*(a/x)*(b/x);
}
return ans;
}
int main()
{
scanf("%d",&n);
if(n==1){puts("0");return 0;}
n--;
g_p();
ll ans=calc(n,n);
printf("%lld\n",ans+2);
return 0;
}