1038. EKG Sequence
Constraints
Time Limit: 5 secs, Memory Limit: 32 MB
Description
The EKG sequence is a sequence of positive integers generated as follows: The first two numbers of the sequence are 1 and 2. Each successive entry is the smallest positive integer not already used that shares a factor with the preceding term. So, the third entry in the sequence is 4 (being the smallest even number not yet used). The next number is 6 and the next is 3. The first few numbers of this sequence are given below.
1, 2, 4, 6, 3, 9, 12, 8, 10, 5, 15, 18, 14, 7, 21, 24, 16, 20, 22, 11, 33, 27
The sequence gets its name from its rather erratic fluctuations. The sequence has a couple of interesting, but non-trivial, properties. One is that all positive integers will eventually appear in the sequence. Another is that all primes appear in increasing order. Your job here is to _nd the position in the sequence of a given integer.
Input
Input consists of a number of test cases. Each case will be a line containing a single integer n, 1 <= n <= 300000. An input of 0 follows the last test case. Note that the portion of the EKG sequence that contains all integers <= 300,000 will not contain an integer >1,000,000.
Output
Each test case should produce one line of output of the form:
The number n appears in location p.
where n is the number given and p is the position of n in the EKG sequence. You are guaranteed that p will be no larger than 1,000,000.
Sample Input
12 21 2 33 100000 299977 0
Sample Output
The number 12 appears in location 7. The number 21 appears in location 15. The number 2 appears in location 2. The number 33 appears in location 21. The number 100000 appears in location 97110.The number 299977 appears in location 584871.
这个题更偏向数学问题,主要难点也就是如何通过上一个数确定下一个数的值。假设我们已知上一个数,这个数的素因子有p1,p2,p3,先以p1为两个数的公因子,然后对p1一直增加一倍,直到这个倍数未出现过,记为a1,然后同样地求出a2,a3,那么a1a2a3中最小的那个就是下一个数的结果。具体算法见代码吧。
// Problem#: 1038 // Submission#: 5060802 // The source code is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License // URI: http://creativecommons.org/licenses/by-nc-sa/3.0/ // All Copyright reserved by Informatic Lab of Sun Yat-sen University #include<iostream> #include<cmath> using namespace std; #define maxn 1000000 int location[maxn];//位置数组,location[i]表示数字i在EKG数列中的位置 int smallest_prime[maxn];//保存最小素数,即smallest_prime[i]保存i的最小素因数 int next_number[maxn];//next_number[i]保存i尚未在数列中出现过的最小倍数 void makeSequence() { location[1]=1;//1和2的位置题目已经给出 location[2]=2; for(int i=2;i<maxn;++i) { if(smallest_prime[i]==0)//找出大于1的每个数的最小素因数 { for(int j=1;i*j<maxn;++j) { if(smallest_prime[i*j]==0) smallest_prime[i*j]=i; } } } for(int i=1;i<maxn;++i)//初始时数列还未开始构造,所以每个数不在数列中的最小倍数为自身 next_number[i]=i; int current_number=2;//currentnumber保存最新确定的数列元素 int smallPrime,temp; for(int i=3;i<maxn;++i)//现在开始求下一个数的值 { temp=current_number;//先将值赋给temp,currentnumber要始终保存最新找到的值 current_number=maxn; while(temp!=1)//主要原理为先找出上个数的最小素因子,并以其作为公因子,寻找最小素因子尚未出现过的最小倍数,然后再找上个数的次小素因子,再以次小素因子作为公因子寻找其尚未出现的最小倍数,依此类推,直到上个数的所有素因子都寻找一遍,然后选择所有结果中最小的那个作为下一个数 { smallPrime=smallest_prime[temp];//temp为上个数的某个素因子 while(location[next_number[smallPrime]]!=0&&next_number[smallPrime]+smallPrime<maxn)//若这个素因子已经出现过,则将最小素因子增加一倍,直到不在数列中出现 next_number[smallPrime]+=smallPrime; current_number=min(current_number,next_number[smallPrime]);//寻找每个素因子求出结果的最小值 while(temp%smallPrime==0)//寻找上个数的下一个素因子,若temp==1则代表已经全部找完 temp/=smallPrime; } location[current_number]=i; } } int main() { int n; makeSequence(); while(cin>>n&&n) { cout<<"The number "<<n<<" appears in location "<<location[n]<<'.'<<endl; } return 0; }