[silicy line]1089. Farey Sequence

Constraints

Time Limit: 1 secs, Memory Limit: 32 MB

Description

The Farey Sequence Fn for any integer n with n >= 2 is the set of irreducible rational numbers a/b with 0 < a < b <= n and gcd(a,b) = 1 arranged in increasing order. The first few are 
F2 = {1/2}
F3 = {1/3, 1/2, 2/3}
F4 = {1/4, 1/3, 1/2, 2/3, 3/4}
F5 = {1/5, 1/4, 1/3, 2/5, 1/2, 3/5, 2/3, 3/4, 4/5}

You task is to calculate the number of terms in the Farey sequence Fn.

Input

There are several test cases. Each test case has only one line, which contains a positive integer n (2 <= n <= 106). There are no blank lines between cases. A line with a single 0 terminates the input.

Output

For each test case, you should output one line, which contains N(n) ---- the number of terms in the Farey sequence Fn.

Sample Input

2
3
4
5
0

Sample Output

1
3
5
9

题目分析:

这个题目就是要求 :小于n并且与n互素的个数,也就是欧拉定理

如果n=(p^x1)*(p2^x2)*(p3^x3)那么 小于n与n互素的元素个数是n*(1-1/x1)*(1-1/x2)*(1-1/x3) ,(p1,p2,p3为素数)这就是欧拉公式

我们只需要根据欧拉公式来求和就可以。

首先把所有素数找出来存在一个数组里面,然后用n来除这些素数(n逐渐变小),知道n小于某个素数的平方,那么n就是最后一个因子,然后根据上面的公式来计算。

/*
*/
#include<iostream>
#include <iomanip>
#include<stdio.h>
#include<cmath>
#include<iomanip>
#include<list>
#include <map>
#include <vector>
#include <string>
#include <algorithm>
#include <sstream>
#include <stack>
#include<queue>
#include<string.h>
#include<set>
using namespace std;

unsigned long long data[1000001];
bool flag[1000001];
vector<int> prime;

void init()
{
	for(int i=2;i<sqrt(1000001.0);i++)
	{
		if(flag[i]==true)
			continue;
		for(int j=2;i*j<1000001;j++)
			flag[i*j]=true;
	}
	for(int i=2;i<1000001;i++)
	{
		if(flag[i]==false)
			prime.push_back(i);
	}
}

int main()
{
	init();
	data[0]=0;
	for(int i=1;i<1000001;i++)
	{
		int value=i+1;
		if(flag[value]==false)
		{
			data[i]=data[i-1]+value-1;
			continue;
		}
		int value1=i+1;//保存最后的结果
		for(int j=0;j<prime.size()&&prime[j]<=value;j++)
		{
			if(prime[j]*prime[j]>value)//剩余的value是一个素数,没有这句超时
			{
				value1=value1/value*(value-1);
				break;
			}
			if(value%prime[j]==0)
			{
				value=value/prime[j];
				value1=value1/prime[j]*(prime[j]-1);
				while(value%prime[j]==0)
					value=value/prime[j];
			}
		}
		data[i]=data[i-1]+value1;
	}
	int n;
	while(cin>>n&&n!=0)
	{
		cout<<data[n-1]<<endl;
	}
}


你可能感兴趣的:([silicy line]1089. Farey Sequence)