HDU4556

xiaoxiao2021-02-28  115

上图是一棵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 /* 可以看到,如果把右半边的数字变成他们的倒数,整个树是关于中间那列对称的. 还有一个性质就是同一行的数字是递增的,这一点很容易得到证明 既然是对称的,只要考虑左半边就行(从0到1),一整行的结果就是半行的结果*2-1 还有一条性质:数字的分子和分母是互质的,同样很容易证明 */ #include<iostream> #include<queue> #include<cstring> #include<vector> #include<string> #include<algorithm> #include<cstdio> #include<cmath> #include<set> #include<cstdlib> #include<stack> typedef long long LL; const int maxsize = 1e6+7; using namespace std; LL Phi[maxsize];//Pri[i]表示i的欧拉函数 void makePhiTable1(int n)//nloglogn { int i; for(i=1;i<=n;i++) Phi[i] = i; //单独的欧拉函数求法Pri[n] = n*(1-1/p1)*(1-1/p2)*(1-1/p3).... //其中p1,p2,p3是n的素数因子 for(i = 2;i<=n;i+=2) Phi[i]/=2;//之所以使用这一步是因为下面有一个循环会穷举所有的因子 for(i=3;i<=n;i++) { if(Phi[i]==i)//说明在i增长到这个i之前,他不是任何之前i的整数倍,所以他是一个素数,所以可以用它来构造以他为因数的欧拉函数 { for(int j=i;j<=n;j+=i) Phi[j] = Phi[j]/i*(i-1); } } } LL getPhi(LL x)//logn { LL i,ret = x; for(i=2;i<sqrt(1.0*x)+1;i++)//sqrt(x)渐渐减小 { if(x%i==0) { ret = ret/i*(i-1); while(x%i==0) x/=i;//循环的次数实际上是这个素数因子的质数 } } if(x>1) ret = ret/x*(x-1);//如果x>1,那么说明x是一个素数 return ret; } LL F[maxsize]; void init(int n) { makePhiTable1((int)1e6+1); F[1] = 2; F[2] = 3; for(int i = 3 ;i<=n;i++) { F[i] = F[i-1] + Phi[i]; } } int main() { //freopen("finput.txt","r",stdin); LL n; init(1000000); //cout<<Phi[88888]<<endl; while(~scanf("%lld",&n)) { printf("%lld\n",2*F[n]-1); } return 0; }
转载请注明原文地址: https://www.6miu.com/read-37583.html

最新回复(0)