zoukankan      html  css  js  c++  java
  • Luogu P2158仪仗队

    欧拉函数

    (1)~(n)中与(n)互质的数的个数被称为欧拉函数,记为(varphi(n))

    [varphi(n)=n*frac{p_{1}-1}{p_{1}} * frac{p_{2}-1}{p_{2}} * ... * frac{p_{m}-1}{p_{m}}=n*prod_{质数p|n}^{} (1-frac{1}{p}) ]

    根据欧拉函数的计算式,在分解质因数的时候求出欧拉函数即可:

    int phi_(int n){
    	int res=n;
    	for(int i=2;i<=sqrt(n);i++){
    		if(n%i==0){
    			res=res/i*(i-1);
    			while(n%i==0) n/=i;
    		}
    	}
    	if(n>1) res=res/n*(n-1);
    	return res;
    }
    

    题解

    题目
    自己推一下很容易发现,一个点((x,y))能被看到,当且仅当(gcd(x,y)=1)
    又因为这是一个方阵,能看到的点关于((1,1))((n,n))的对角线是对称的,所以求出一半的点的数量(ans)(不包括((1,1))),(ans imes2+1)即为最终结果

    • 为什么加和的时候是(1)~((n-1))?
      因为点((1,1))是不包括的,三角形只有((n-1))
    • 为什么要特判(n==1)?
      因为只有一个点((1,1))的时候就是他看到的就是0个啊

    code

    纯欧拉函数

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #define maxn 40010
    using namespace std;
    template<typename T>
    inline void read(T &x){
    	x=0; bool flag=0; char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') flag=1;
    	for(;isdigit(c);c=getchar()) x=x*10+(c^48);
    	if(flag) x=-x;
    }
    
    int n;
    int ans,phi[maxn];
    
    int phi_(int n){
    	int res=n;
    	for(int i=2;i<=sqrt(n);i++){
    		if(n%i==0){
    			res=res/i*(i-1);
    			while(n%i==0) n/=i;
    		}
    	}
    	if(n>1) res=res/n*(n-1);
    	return res;
    }
    
    int main(){
    	read(n);
    	if(n==1){cout<<0<<endl; return 0;}
    	for(int i=1;i<=n;i++) phi[i]=phi_(i);
    	for(int i=1;i<=n-1;i++) ans+=phi[i];
    	cout<<2*ans+1<<endl;
    	return 0;
    }
    

    Eratosthenes筛法

    (O(n log n))

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #define maxn 40010
    using namespace std;
    template<typename T>
    inline void read(T &x){
    	x=0; bool flag=0; char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') flag=1;
    	for(;isdigit(c);c=getchar()) x=x*10+(c^48);
    	if(flag) x=-x;
    }
    
    int n;
    int ans,phi[maxn];
    
    void phi_(int n){
    	for(int i=1;i<=n;i++) phi[i]=i;
    	for(int i=2;i<=n;i++){
    		if(phi[i]==i){
    			for(int j=i;j<=n;j+=i){
    				phi[j]=phi[j]/i*(i-1);
    			}
    		}
    	}
    }
    
    int main(){
    	read(n);
    	if(n==1){cout<<0<<endl; return 0;}
    	phi_(n);
    	for(int i=1;i<=n-1;i++) ans+=phi[i];
    	cout<<2*ans+1<<endl;
    	return 0;
    }
    //Eratosthenes筛法,O(n log n)
    

    线性筛

    (O(n))

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cstdlib>
    #define maxn 40010
    using namespace std;
    template<typename T>
    inline void read(T &x){
    	x=0; bool flag=0; char c=getchar();
    	for(;!isdigit(c);c=getchar()) if(c=='-') flag=1;
    	for(;isdigit(c);c=getchar()) x=x*10+(c^48);
    	if(flag) x=-x;
    }
    
    int n;
    int ans,cnt,mindiv[maxn],isprime[maxn],phi[maxn];
    
    void phi_(int n){
    	cnt=0;//质数数量 
    	memset(mindiv,0,sizeof(mindiv));//最小质因子
    	phi[1]=1;
    	for(int i=2;i<=n;i++){
    		if(mindiv[i]==0){//i是质数 
    			mindiv[i]=i;
    			isprime[++cnt]=i;
    			phi[i]=i-1; 
    		}
    		for(int j=1;(j<=cnt)&&(i*isprime[j]<=n);j++){
    			mindiv[i*isprime[j]]=isprime[j];
    			phi[i*isprime[j]]=phi[i]*(i%isprime[j]?isprime[j]-1:isprime[j]);//"isprime[j]-1" and "phi[isprime[j]]" both right
    			if(mindiv[i]==isprime[j]) break;
    		}
    	} 
    	
    }
    
    int main(){
    	read(n);
    	if(n==1){cout<<0<<endl; return 0;}
    	phi_(n);
    	for(int i=1;i<=n-1;i++) ans+=phi[i];
    	cout<<2*ans+1<<endl;
    	return 0;
    }
    //线性筛,O(n) 
    
  • 相关阅读:
    微信企业号第三方应用开发[二]——创建应用
    微信企业号第三方应用开发[一]——创建套件
    微信企业号第三方应用开发[目录]
    微信企业号第三方应用开发[前言]
    基于netty的心跳机制实现
    Jquery使select、radio某项选中
    画廊插件baguetteBox
    HTML5实现下载文件且指定下载文件名
    Python的生成器和生成器表达式
    Python的闭包以及迭代器
  • 原文地址:https://www.cnblogs.com/DReamLion/p/14498370.html
Copyright © 2011-2022 走看看