歐拉函數(例題)


φ//如果不熟悉歐拉函數可轉超鏈接<--

正題:

1.儀仗隊

求從(0,0)點可以看到的點,我們考慮正比例函數的斜率,同一斜率上只能看到一個點,我們要知道對於斜率0~1在一個n*n的點陣中有多少可能的斜率使得有若干點在函數上。

觀察規律:

1*1:顯然答案為0(自己看到自己當然不算了)

2*2:有斜率0,1/2(當然0是重的,一下重復的就不再考慮了),所以多了一種,答案為1

3*3:多了1/3,2/3,答案為3

4*4:多了1/4,2/4,3/4;2/4重了,所以答案為5

5*5:多了1/5,2/5,3/5,4/5,答案為9

......

n*n:多了1/n,2/n,3/n,4/n,......,(n-1)/n中不重復的,不重復就是說分數要最簡。

那就成了求1~n中所有數i中1~i-1中與i互質的數的個數只和,即為歐拉函數。

求出和來之后最終答案應該為2*ans+1(我們算過了y=x的下半邊三角形的情況,還有上半邊呢?)

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
bool b[100010];
int n,prime[100010],total,phi[100010],ans;
int main()
{
    scanf("%d",&n);
    b[0]=b[1]=1;
    phi[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(!b[i])
        {
            prime[++total]=i;
            phi[i]=i-1;
        }
        for(int j=1;j<=total;j++)
        {
            if(i*prime[j]>n)break;
            b[i*prime[j]]=1;
            if(i%prime[j]==0)
            {
                phi[i*prime[j]]=phi[i]*prime[j];
                break;
            }
            else
            phi[i*prime[j]]=phi[i]*(prime[j]-1);
        }
    }
    for(int i=1;i<=n-1;i++)ans+=phi[i];
    printf("%d",ans*2+1);
}

  

2.Farey Sequence:

題目描述:對於任意整數n>1,存在分數集合序列F,Fi=a/b,其中0<a<b≤n,且(a,b)=1.給定T個正整數n,求Fn的項數。

 

解:

我們看這個集合的實質,集合不能有重復元素,所以分數必須是最簡,那就是說對b∈[1,n],a∈[1,b-1]中滿足(a,b)互質的對數。

即求φ(1)+φ(2)+φ(3)+...+φ(n),由於數據有多組,我們考慮預處理,用前綴和記錄對任意n的答案。

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
bool b[100010];
int n,prime[100010],total,phi[100010],ans[100010];
int main()
{
	
    n=100000;
    b[0]=b[1]=1;
    phi[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(!b[i])
        {
            prime[++total]=i;
            phi[i]=i-1;
        }
        for(int j=1;j<=total;j++)
        {
            if(i*prime[j]>n)break;
            b[i*prime[j]]=1;
            if(i%prime[j]==0)
            {
                phi[i*prime[j]]=phi[i]*prime[j];
                break;
            }
            else
            phi[i*prime[j]]=phi[i]*(prime[j]-1);
        }
    }
    for(int i=2;i<=n;i++)
    ans[i]=ans[i-1]+phi[i];
    int t;
    scanf("%d",&t);
    for(int i=1;i<=t;i++)
    {
    	scanf("%d",&n);
    	printf("%d\n",ans[n]);
	}
}

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM