其他分享
首页 > 其他分享> > H-Subprime Fibonacci Sequence ---2018纽约区域赛(埃氏筛的运用及map与pair的嵌套)

H-Subprime Fibonacci Sequence ---2018纽约区域赛(埃氏筛的运用及map与pair的嵌套)

作者:互联网

Subprime Fibonacci Sequence

题目链接http://acm.csu.edu.cn:20080/csuoj/problemset/problem?pid=2277

Time Limit: 1 Sec Memory Limit: 128 Mb

Description

The Subprime function,SP(n)of a positive integer n, is defined by:
SP(n)=n if n is 1 or a prime
Otherwise,
在这里插入图片描述
A Subprime Fibonacci sequence, an, is defined by:

在这里插入图片描述
For example:
0, 1, 1, 2, 3, 5, 4, 3, 7, 5, 6, 11, 17, 14, 31, 15, …
Unlike the standard Fibonacci sequence which grows exponentially, a Subprime Fibonacci sequence usually eventually repeats. Write a program which takes as input the initial values a0 and a1 and a number of terms to compute n and determines whether the sequence starting with a0 and a1repeats in the first n terms

The sequence repeats if there are integers k and m with k < m < n for which,
在这里插入图片描述
The length of the repeating sequence is (m – k) if there is no integer j, k < j < m 在这里插入图片描述I.e. the sequence from k to m is the shortest repeating sequence

Input

The first line of input contains a single decimal integer P,(1 ≤ p ≤ 1000), which is the number of data sets that follow. Each data set should be processed identically and independently

Each data set consists of a single line of input. It contains the data set number, K, followed by the maximum number, n(0 < n ≤ 1000) of terms to compute followed by the initial values a0 and a1 in that order, (0 < a0, a1 ≤ 1000)

Output

For each data set there are multiple lines of output. If a repeating sequence is found, the first line of output contains the data set number, K, followed by the index m where the sequence first repeated followed by the length of the shortest repeating subsequence. The following lines of output contain the (length + 2) terms of the sequence from term (k-1) to term (m), 20 terms to a line (except possibly for the last line). If a repeating sequence is not found in the first n terms, the first line of output contains the data set number, K, followed by the number of terms n followed by the digit 0. The following line contains only the value an of the sequence at n(the (n + 1)^th term).

Sample Input

3
1 1000 0 1
2 10 31 23
3 200 15 17

Sample Output

1 57 18
48 13 61 37 49 43 46 89 45 67 56 41 97 69 83 76 53 43 48 13
2 10 0
88
3 137 136
15 17 16 11 9 10 19 29 24 53 11 32 43 25 34 59 31 45 38 83
11 47 29 38 67 35 51 43 47 45 46 13 59 36 19 11 15 13 14 9
23 16 13 29 21 25 23 24 47 71 59 65 62 127 63 95 79 87 83 85
84 13 97 55 76 131 69 100 13 113 63 88 151 239 195 217 206 141 347 244
197 147 172 29 67 48 23 71 47 59 53 56 109 55 82 137 73 105 89 97
93 95 94 63 157 110 89 199 144 49 193 121 157 139 148 41 63 52 23 25
24 7 31 19 25 22 47 23 35 29 32 61 31 46 11 19 15 17


emmm。。。题目大意是这样的:先定义sp(n)=n,如果n是1或素数。否则sp(n)=n/s[n],s[n]代表n的最小素因子。接下来我们定义一个另类的斐波那契数列:a[n]=sp(a[n-1]+a[n-2]),其中边界a[0],a[1]是自定义的。输入:样例编号,步数n,a[0],a[1]。让我们在n步之内找到重复的位置和重复的长度。如果可以,则输出样例编号,最小重复位置,重复长度,然后输出重复的信息+重复的头两个信息。如果不能找到,则输出样例编号,n,0,a[n]。
看过我“一个部族,一个民族,一个弗雷尔卓德(素数筛+线段树)”这篇博客的应该知道怎么线性求一个数的最小素因子。就是在埃氏筛的同时求出它的最小素因子:

for (int i=2; i<=m; i++) {
	if (!vis[i])
		for (int j=i*i; j<mac; j+=i) {
			vis[j]=1;
			if (!prim[j]) prim[j]=i;//存j的最小素因子为i
		}
}

然后接下来就是找重复。这个实际上不需要判断所有的是否重复,只需要判断相邻的两个是否重复就行了,因为第三个是由第一个和第二个转化而来,如果第一和二个重复了,那么第三个绝对也会重复,以此类推。。。
那么我们只需将前两个的数进行映射,map只能单个映射,所以选择pair,然后用map嵌套pair判断是否这两个数已经出现:

typedef pair<int,int>p;
map<p,int>q;
q[make_pair(a[0],a[1])]=1;
for (int i=2; i<=k; i++) {
	a[i]=sp(a[i-1]+a[i-2]);
	if (q[make_pair(a[i-1],a[i])]) {
		first=a[i-1],second=a[i];
		mark=i;
		end=i-2;
		break;
	}
	q[make_pair(a[i-1],a[i])]=1;
}

然后。。。就没有然后了,这一题就over了。。。注意题目二十个数换一行。
AC代码:

#include <cstdio>
#include <cmath> 
#include <cstring>
#include <map>
#include <algorithm>
using namespace std;
#define mac 1000000
int a[mac+10]={0},prim[mac+10]={0},vis[mac+10]={0};
int sp(int x)
{
	if (!vis[x]) return x;
	return x/prim[x];
}
int main()
{
	int t,id,k;
	scanf ("%d",&t);
	int m=sqrt(mac);
	for (int i=2; i<=m; i++){
	    if (!vis[i])
	    	for (int j=i*i; j<mac; j+=i){
	    		vis[j]=1;
	    		if (!prim[j]) prim[j]=i;
			} 		
	}
	for (int i=1; i<=mac; i++) if (!vis[i]) prim[i]=i;
	int o=0;
	while (t--){
		o++;
		typedef pair<int,int>p;
		map<p,int>q;
		scanf ("%d%d%d%d",&id,&k,&a[0],&a[1]);
		int first=-1,second=-1,mark,end,len,ex=0;
		q[make_pair(a[0],a[1])]=1;		
		for (int i=2; i<=k; i++){
			a[i]=sp(a[i-1]+a[i-2]);
			if (q[make_pair(a[i-1],a[i])]) {
				first=a[i-1],second=a[i];
				mark=i;end=i-2;break;
			}
			q[make_pair(a[i-1],a[i])]=1;		
		}
		printf ("%d ",o);
		int num=0;
		for (int i=0; i<k; i++){
			if (a[i]==first && a[i+1]==second){
				len=end-i+1;ex=1;
				printf ("%d %d\n",mark,len);
				for (int j=i; j<=end+2; j++){
					num++;
					if (num%20==0) printf ("%d\n",a[j]);
					else printf ("%d ",a[j]);
				}
				break;
			}
		} 
		if (num%20) printf ("\n");
		if (!ex){
			printf("%d 0\n",k);
			printf ("%d\n",a[k]);
		}		
	}
	return 0;
}

标签:map,13,埃氏,sequence,int,Sequence,number,line,data
来源: https://blog.51cto.com/u_15249461/2870458