BZOJ-2190(儀仗隊)(歐拉函數)

BZOJ-2190(儀仗隊)(歐拉函數)
Crawling in process...Crawling failedTime Limit:10000MS    Memory Limit:265216KB     64bit IO Format:%lld & %llu

Description

  作爲體育委員,C君負責這次運動會儀仗隊的訓練。儀仗隊是由學生組成的N * N的方陣,爲了保證隊伍在行進中整齊劃一,C君會跟在儀仗隊的左後方,根據其視線所及的學生人數來判斷隊伍是否整齊(如下圖)。  

  

   現在,C君希望你告訴他隊伍整齊時能看到的學生人數。

Input

  共一個數N。

Output

  共一個數,即C君應看到的學生人數。

Sample Input

  4

Sample Output

  9


Hint

【數據規模和約定】   對於 100% 的數據,1 ≤ N ≤ 40000

//注:把體育委員所處點看作原點(0,0)。於是可以發現體育委員可以看到的點(x,y),滿足x與y互質,可以利用歐拉函數性質求解。注意:(1,1),(1,0)  (0,1)這三個點比較特殊。

//輸出要用%lld,不能用%64d,會PE.

歐拉函數性質:

記;x的歐拉函數值爲 f(x),

則:

,其中p1,p2,p3........pn,爲x的所有質因數,x是正整數。

其他性質:

(1):若n是質數p的k次冪,f(n)=p^k-p^(k-1)=(p-1)*p^(k-1),因爲除了p的倍數外,其他數都和n互質。

(2):若m、n互質,f(m*n)=f(m)*f(n);

(3):當n爲奇數時,f(2*n)=f(n);

(4):若n爲素數,則   f(n)=n-1;

此題在加上素數判斷後,跑了4000毫秒,之前不加素數判斷,跑了10000毫秒。

My   solution:

/*2016.3.15*/

#include<stdio.h>
#include<string.h>
int vis[40020];
long long ans;
int n;
void  prim()//素數打表 
{
	int i,j,k;
	memset(vis,0,sizeof(vis));
	vis[1]=1;
	for(i=2;i<40020;i++)
	{
		for(j=2;j*i<40020;j++)
		 vis[i*j]=1;
	}
    return ;
}
long long er(int m)
{
	long long i,cnt=m;
	if(vis[m])//如果m是素數,m的歐拉函數值爲m-1 
	{
		for(i=2;i<=m;i++)
		{
			if(m%i==0)//i爲m的質因子,因爲i從2開始,如;不可能有m%4==0,m%6==0等情況的出現 ,當i=2時就已經處理過m了,處理過後的m%2!=0,
		          //因此更不可能m%4==0,同理m%6==0的情況也不可能出現。只有:當且僅當i爲m的質因子時纔有可能滿足m%i==0 
			{
				cnt-=cnt/i;
				while(m%i==0)//這條語句保證i是m的質因子 
				m/=i;
			}
		}
		return cnt;
	}
	else
	return m-1;
	
}
int main()
{
	long long i,j,k,count;
	prim();
	while(scanf("%lld",&n)==1)//用%I64d輸出結果,格式錯誤 
	{
		count=0;
		if(n==1)//容易忽略,當n=1時,只有自己一個人,看到別人的數目爲0 
		printf("0\n");
		else
		{
			for(i=1;i<=n-1;i++)
			count+=er(i);//求小於i且與i互質的因子的個數 ,然後累加 
			count*=2;//對角線的上方和下方兩部分,所以乘以2 ,不過(1,1)被加了兩次 ,應減1 
			count+=1;//(1,0)和(0,1)兩個位置也滿足題意,減1再加2 
			printf("%lld\n",count); 
		}
	}
	return 0;
}


發佈了144 篇原創文章 · 獲贊 10 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章