• [SDOI2008]仪仗队


    洛谷

    POJ(POJ我真的无力吐槽,从来就没有AC过)

    题意:有一个N*N的方阵,求站在方阵左下角,能看到多少个点?

    分析:我习惯于把左下角的点看作(1,1).我们以初中数学的思维来看,本题就是斜率相同的直线上只能看到第一个点.我们想办法转换成计算机能理解的语言,例如对于两个点(4,6)和(2,3),这两个点在同一条直线上,所以我们只能看到(2,3).

    通过这个例子你有没有发现,对于一个点(x,y),如果它能被我们看见,当且仅当满足(gcd(x,y)=1).其实很好理解,反证法,如果(gcd(x,y)!=1),我们设(d=gcd(x,y)),则这个点一定会被((x/d,y/d))这个点挡住.

    所以本题我们实际上要求的就是对于一个y,有多少x与y互质,其中1<x<y,这不就是欧拉函数phi(y)吗?

    然后像上面那样考虑的话,其实只考虑了方阵的一半,所以答案要乘2.

    我们把第一行和第一列单独拎出来看,因为任意一个数与1的gcd都是1,而显然第一行和第一列,我们都只能看到第一个,也就是(1,2)和(2,1),然后(1,1)本身也能被看到,所以ans+=3.

    所以我们只需要线性筛出n以内的欧拉函数,然后输出(ans=3+2*sum_{i=2}^{n}phi[i])

    如果不会线性筛欧拉函数,戳这里

    int n,m,ans;
    int v[40005],prime[40005],phi[40005];
    void get_phi(){//模板
        for(int i=2;i<=40005;i++){
    		if(v[i]==0){
    	    	v[i]=i;prime[++m]=i;
    	    	phi[i]=i-1;
    		}
    		for(int j=1;j<=m;j++){
    	    	int cnt=prime[j]*i;
    	    	if(prime[j]>v[i]||cnt>40005)break;
    	    	v[cnt]=prime[j];
    	    	if(i%prime[j])phi[cnt]=phi[i]*(prime[j]-1);
    	    	else phi[cnt]=phi[i]*prime[j];
    		}
        }
    }
    int main(){
        get_phi();
        n=read();
        if(n==0||n==1){puts("0");return 0;}//特判
        for(int i=2;i<n;i++)ans+=phi[i];
        ans*=2;ans+=3;
        printf("%d
    ",ans);
        return 0;
    }
    
    
  • 相关阅读:
    Android中的5种数据存储方式
    Android Service
    Android BroadcastReceiver
    Android Intent
    Android Fragment
    Android 教学实验计划1
    【Android教学用例程序】计算器
    Android UI 基础知识
    Android 控件
    Android 计算器布局测试2
  • 原文地址:https://www.cnblogs.com/PPXppx/p/10461030.html
Copyright © 2020-2023  润新知