Stern-Brocot Tree HDU - 4556
上圖是一棵Stern-Brocot樹,其生成規則如下:
從第1行到第n行,每行相鄰兩數a/b和c/d,產生中間數(a+c)/(b+d),置於下一行中。將一行的分數(包括0/1,1/0),進行約分簡化,則每一行(包括0/1,1/0,1/1),不會出現兩個相同的分數。若分子或者分母大於n,則去掉該分數,將剩下的分數,從小到大排序,得到數列F。
現在請您編程計算第n行的數列F的個數。
Input
輸入包含多組測試用例,每組輸入數據是一個正整數n(n<=1000000)。
Output
對於每組的測試數據n,請輸出第n行的數列F的個數。
Sample Input
1
2
4
6
Sample Output
3
5
13
25
題意:
法裏數列長度f[n]=f[n-1]+φ(n)(這裏的長度值0-1的長度)
因爲這個題還有對稱的另一半所以只需要歐拉函數乘2即可f[n]=f[n-1]+2*φ(n)
code:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
#define maxn 1000005
#define ll __int64
ll phi[maxn],ans[maxn];
void init()
{
phi[1]=1;
for(int i=2;i<maxn;i++)
{
if(!phi[i])
{
for(int j=i;j<maxn;j+=i)
{
if(!phi[j])
phi[j]=j;
phi[j]-=phi[j]/i;
}
}
}
ans[1]=3;
for(int i=2;i<maxn;i++)ans[i]=ans[i-1]+2*phi[i];
}
int main()
{
init();
int n;
while(~scanf("%d",&n))
{
printf("%I64d\n",ans[n]);
}
return 0;
}