1. 程式人生 > >UVA 11426 (歐拉函數&&遞推)

UVA 11426 (歐拉函數&&遞推)

out algo pan 函數 iostream ons 現實 color clu

題意:給你一個數N,求N以內和N的最大公約數的和

解題思路:

一開始直接想暴力做,4000000的數據量肯定超時。之後學習了一些新的操作。

題目中所要我們求的是N內gcd之和,設s[n]=s[n-1]+gcd(1,n)+gcd(2,n)+gcd(3,n)+gcd(4,n).......

再設f[n]=gcd(1,n)+gcd(2,n)+gcd(3,n)+gcd(4,n).......;

思考一下,假設gcd(x,n)=ans,ans便是x和n的最大公約數,那麽有幾個ans我們將某ans的個數sum(num*ans)是不是就是當前f[n]的值;

那麽某個ans的個數num我們該怎麽求???

gcd(x,n)=ans;那麽gcd(x/ans,n/ans)就是1;就是說x/ans和n/ans是互素的,那麽求n以內和n互素的數的個數我們怎麽辦???就用歐拉函數phi;

其個數就是phi[n/ans];

然後,,,,你以為求這點就做完了是嗎??玩笑,,,;

你可以直接打出4000 000歐拉表,那麽我們該怎麽遍歷賦值f[n];f[n]=num*ans;我們遍歷n在遍歷ans麽??這個不現實,在當前這個n中會有部分ans白白計算

所以我們最好的辦法就是先行枚舉ans,我們知道,當前ans所對應的n一定是ans的倍數,所以我們遍歷n極為方便,只需要令n=2*ans,3*ans,4*ans,5*ans......

這裏有個點就是n不能是ans,所以我們第二重循環裏就應該從2*ans開始;這個地方一會在代碼中點出;

具體就是這麽多;

AC代碼

 1 #include<stack>
 2
#include<queue> 3 #include<cmath> 4 #include<cstdio> 5 #include<cstring> 6 #include<iostream> 7 #include<algorithm> 8 9 using namespace std; 10 11 #define INF 0x3f3f3f3f 12 typedef long long ll; 13 const ll maxn = 4000005; 14 ll n; 15 16 ll euler[maxn]; 17 ll fun_[maxn];
18 19 void euler_(ll maxn) 20 { 21 for (int i=1;i<=maxn;i++) 22 { 23 euler[i]=i; 24 } 25 for (int i=2;i<maxn;i++) 26 { 27 if (euler[i]==i) 28 { 29 for (int j=i;j<maxn;j+=i) 30 { 31 euler[j]=euler[j]/i*(i-1); 32 // cout<<euler[j]<<endl; 33 } 34 } 35 } 36 } 37 38 ll s[maxn]; 39 40 41 int main() 42 { 43 euler_(maxn); 44 //memset(fun_,0,sizeof(fun_)); 45 for (int i=1;i<=maxn;i++) 46 { 47 for (int j=i+i;j<=maxn;j+=i) 48 { 49 //cout<<i<<" "<<n/i<<" "<<euler[n/i]<<endl; 50 51 fun_[j]+=i*euler[j/i]; 52 //cout<<fun_[j]<<endl; 53 } 54 } 55 s[1]=0; 56 57 for (int i=2;i<=maxn;i++) 58 { 59 s[i]=s[i-1]+fun_[i]; 60 //cout<<i<<" "<<s[i]<<endl; 61 }//cout<<"***********"<<endl; 62 while (cin>>n&&n) 63 { 64 //cout<<n<<endl; 65 cout<<s[n]<<endl; 66 } 67 }

UVA 11426 (歐拉函數&&遞推)