二分與三分
阿新 • • 發佈:2020-12-20
技術標籤:數論
在一個平面直角座標系的第一象限內,如果一個點(x,y)與原點(0,0)的連線中沒有通過其他任何點,則稱該點在原點處是可見的。
例如,點(4,2)就是不可見的,因為它與原點的連線會通過點(2,1)。
部分可見點與原點的連線如下圖所示:
編寫一個程式,計算給定整數N的情況下,滿足0≤x,y≤N0≤x,y≤N的可見點(x,y)的數量(可見點不包括原點)。
題意:從原點發出光線,可以照到的柱子的數量,光線會被第一個柱子擋住。
題解:
每一條直線都是y=kx,,被照到的柱子都是這條直線上的第一個點,
設這個點為x0,y0,那麼y=y0/x0x,這個時候,既然是第一個點,那麼y0和x0就不能有公約數,不然還可以再化簡成更小的點,所以y0和x0是互質的,,,又關於y=x對稱軸,兩邊的點的數量是一樣的,所以只算下面的點就行,,,所以答案就是1-n之間的所有數的尤拉函式,即<=i的數與i這個數互質的個數,,,求和最後
這裡用了一個尤拉函式線性模板,修該一下尤拉篩就行。
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
int vis[N+19];
int prime[N+19];
int phi[N+10];
int cnt;
void init(int n) //尤拉函式線性模板
{
phi[1]=1;
vis[0]=vis[1]=1;
cnt=0;
for(int i= 2; i<=n; i++)
{
if(vis[i]==0)
{
prime[cnt++]=i;
phi[i]=i-1;
}
for(int j=0; prime[j]*i<=n; j++)
{
vis[prime[j]*i]=1;
if(i%prime[j]==0)
{
phi[i*prime[j]]=phi[i]*prime[j];
break ;
}
phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
}
return ;
}
int main()
{
int c;
scanf("%d",&c);
init(2000);
int Case=0;
while(c--)
{ Case++;
int n;
scanf("%d",&n);
int sum=0;
for(int i=1; i<=n; i++)
{
sum+=phi[i];
}
printf("%d %d %d\n",Case,n,sum*2+1);
}
return 0;
}