HDU——2824 The Euler function
The Euler function
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4507 Accepted Submission(s): 1872 Problem Description The Euler function phi is an important kind of function in number theory, (n) represents the amount of the numbers which are smaller than n and coprime to n, and this function has a lot of beautiful characteristics. Here comes a very easy question: suppose you are given a, b, try to calculate (a)+ (a+1)+....+ (b)
Input
There are several test cases. Each line has two integers a, b (2<a<b<3000000).
題目大意:
給出n,m,你需要求出從n到m所有歐拉函數的值。
思路:
先看代碼吧。。。。
代碼:
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define N 3000010 using namespace std; int n,m; long long ans,phi[N]; void get_phi() { phi[1]=0; for(int i=2;i<=N;++i) { if(i&1) phi[i]=i; else phi[i]=i/2; } phi[2]+=phi[1]; for(int i=3;i<=N;i+=2) { if(phi[i]==i) for(int j=i;j<=N;j+=i) phi[j]=phi[j]/i*(i-1); phi[i]+=phi[i-1],phi[i+1]+=phi[i]; } } int main() { get_phi(); while(~scanf("%d%d",&n,&m)) { ans=phi[m]-phi[n-1]; printf("%lld\n",ans); } return 0; }
哈哈,看不明白對吧
顯然,我也看不明白。。。。
好了,大體說說吧。 我們還是用歐拉函數來解這道題(廢話(#‵′)凸)
但是我們顯然不能直接暴力枚舉(為什麽??)(T成狗啊!!!!)可能您寫的好看說不定就過了是吧(雖然不大可能吧。。。。因為有多組數據啊(無奈 )),反正我是T成狗了。。。。
既然這樣不行,那我們就找個方便一點的做法。這是有的大佬就想到了,要不我們打個歐拉函數表吧(說白了就是打個表,用個數組把每個歐拉函數值都存起來)(蒟蒻頭一回聽說這個東西,長見識),不過好像還是T。。。。因為我們有多組數據,對於每一組數據我們都要o(n)查詢
我們再找個方便一點的做法,要不我們用一個前綴和吧。(欸,好像可行。。。)這樣我們就只需要處理一次,再對於每一組詢問o(1)查詢就好了
當然又有人要問了,怎麽處理?? 這個。。。。蒟蒻表示也不太懂,但我還是盡量說明白吧(若果有明顯錯誤的地方,請不要聽我瞎bibi)
首先我們先把數據處理到N(為什麽?? 因為這樣我們可以只處理一次,減小時間復雜度啊。 可是這樣我們不就多處理了很多嗎??那時間復雜度不是更高了嗎?? ORZ,因為我們是有多組數據啊,我們不知道他最大的m是幾啊,省得我們再對於每一組詢問都要處理一次了),對於循環到的數,我們先判斷她是奇數還是偶數,如果是偶數的話,那麽就先把他的歐拉函數值附成i/2(為什麽?? 你看啊,2的歐拉函數值是不是1,4的歐拉函數值是不是2,6的歐拉函數值是不是2,8的歐拉函數值是不是4.。。。。。。這樣是不是就可以推出n(為偶數)的歐拉函數值一定比n/2小 好吧,我們可以這樣想,偶數一定與偶數不互質,那麽我們就排除了n/2個數)如果是奇數的話我們就把他的歐拉函數值附成i,接下來我們再進行一遍循環,來篩掉與每個數不互質的數的個數。
for(int i=3;i<=N;i+=2)//這個地方我們只循環奇數,因為對於偶數我們前面已經把與他一定不互質的數(偶數)排除了,那麽如果
{ //這個數還有與她不互質的數,那麽這個最大公約數一定是奇數,不然一定早被篩掉了。。。。。
if(phi[i]==i)//如果這個數沒有被處理過
for(int j=i;j<=N;j+=i)//跟歐拉篩一樣是每個數都被他最小的因子所篩去
phi[j]=phi[j]/i*(i-1);//歐拉函數公式
phi[i]+=phi[i-1],phi[i+1]+=phi[i];//計算前綴和
}
應該明白了吧。。。。
HDU——2824 The Euler function