• 洛谷P2158 欧拉函数


    题意:

    有一个 n × n n\times n n×n的方阵,有一个观察者站在 ( 1 , 1 ) (1,1) (1,1),问他能看到多少个除 ( 1 , 1 ) (1,1) (1,1)外的点

    Solution:

    视线是个射线,我们考虑经过远点的某条直线 y = k x y=kx y=kx,如果存在一个点 ( x 0 , y 0 ) (x_{0},y_{0}) (x0,y0)在直线上,那么 2 x 0 , 2 y 0 2x_{0},2y_{0} 2x0,2y0也在直线上,但这是看不到的,于是,对每个斜率 k k k,只有满足 y x = k \frac{y}{x}=k xy=k g c d ( x , y ) = 1 gcd(x,y)=1 gcd(x,y)=1的点才能被看到,斜率值域是 ( − ∞ , + ∞ ) (-\infty,+\infty) (,+),于是只需要满足 g c d ( x , y ) = 1 gcd(x,y)=1 gcd(x,y)=1的点都能被 ( 0 , 0 ) (0,0) (0,0)的观察者看到(由于 ( 0 , y ) , ( x , 0 ) (0,y),(x,0) (0,y),(x,0)斜率特殊,需要特判)

    那么在原题,只需要满足 g c d ( x − 1 , y − 1 ) = 1 gcd(x-1,y-1)=1 gcd(x1,y1)=1的点,就可以被看到,其中 x ∈ [ 2 , n ] , y ∈ [ 2 , n ] x\in[2,n],y\in[2,n] x[2,n],y[2,n],即满足 x ∈ [ 1 , n − 1 ] , y ∈ [ 1 , n − 1 ] , g c d ( x , y ) = 1 x\in[1,n-1],y\in[1,n-1],gcd(x,y)=1 x[1,n1],y[1,n1],gcd(x,y)=1的点都能被看到,不妨令 x ≥ y x\geq y xy,这就是 ϕ ( x ) \phi(x) ϕ(x),同理 x ≤ y x\leq y xy时是 p h i ( y ) phi(y) phi(y),需要注意的是,当 n ≠ 1 n\neq1 n=1时, ( 2 , 2 ) (2,2) (2,2)点会被计算两次,需要减去一次,当 n = 1 n=1 n=1时,不存在 ( 1 , 2 ) , ( 2 , 1 ) (1,2),(2,1) (1,2),(2,1),不需要+2

    答案即

    ( 2 ∑ i = 1 n − 1 ϕ ( i ) ) − 1 + 2 , n > 1 (2\sum_{i=1}^{n-1}\phi(i))-1+2,n>1 (2i=1n1ϕ(i))1+2,n>1

    0 , n = 1 0,n=1 0,n=1

    // #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    using namespace std;
    
    using ll=long long;
    const int N=40005,inf=0x3fffffff;
    const long long INF=0x3f3f3f3f3f3f,mod=1e9+7;
    
    int n,cnt,prime[N],phi[N];
    bool isprime[N];
    
    void make_prime()
    {
    	memset(isprime,true,sizeof(isprime));
    	phi[1]=1; isprime[0]=isprime[1]=false;
    	for(int i=2;i<N;i++)
    	{
    		if(isprime[i])
    		{
    			prime[++cnt]=i;
    			phi[i]=i-1;
    		}
    		for(int j=1;j<=cnt&&i*prime[j]<N;j++)
    		{
    			isprime[i*prime[j]]=false;
    			if(i%prime[j]==0)
    			{
    				phi[i*prime[j]]=prime[j]*phi[i];
    				break;
    			}
    			else phi[i*prime[j]]=phi[i]*(prime[j]-1);
    		}
    	}
    }
    
    int main()
    {
    	cin>>n;
    	make_prime();
    	ll ans=0;
    	for(int i=1;i<n;i++) ans+=phi[i]<<1;
    	cout<<ans+(n!=1);
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
  • 相关阅读:
    OSPF双栈原理
    科技作者吴军:不用低效率的算法做事情
    网络协议的基本概念
    网络安全之反弹Shell
    Android lint配置及使用
    后端思维篇:如何抽一个观察者模板
    敢问路在何方
    Two-Stream Consensus Network论文阅读
    prompt learning——你需要掌握的基础知识以及离散型 prompt 的代码
    UE4 距离场
  • 原文地址:https://blog.csdn.net/stdforces/article/details/127661708