【校内模拟】数列

![](https://img2018.cnblogs.com/blog/1340330/201810/1340330-20181019080446315-1580382296.png)

这是一套模拟题的(T1)

看完题我首先想到的是找规律

我人工推了几项后发现了一点鬼畜的规律,然后就打了代码

直到爆零之后发现它不是一道找规律的题

看完题解我感觉无(F**K)

为什么(T1)如此毒瘤(其实是我太菜)

题解:

显然根据斐波那契数列,第(50)个字符串的长度一定远超过了(2^{31})的范围

我们不妨将大于(50)(n) 奇数看作(49),偶数看作(48)

我们可以将前(20)个字符串预处理出来

(nleq 20)时直接输出答案

否则设一个函数(solve(n,l,r))递归到(n-2)(n-1)

(l)(r)的递归需要知道第(n-2)个字符串的长度

预处理斐波那契数列即可

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define LL long long
int n,l,r;
LL f[50];
string s[21];
void solve(int t,int x,int y){
	if(x>y||x>=f[t]) return;
	if(t<=20){
		for(int i=x;i<=y;++i)
			putchar(s[t][i]);
		return;
	}
	if(f[t-2]-1>=y)
		solve(t-2,x,y);
	else if(f[t-2]<=x)
			solve(t-1,x-f[t-2],y-f[t-2]);
	else {
		solve(t-2,x,f[t-2]-1);
		solve(t-1,0,y-f[t-2]);
	}
}
int main()
{
	freopen("sequence.in","r",stdin);
	freopen("sequence.out","w",stdout);
	scanf("%d%d%d",&n,&l,&r);
	if(n>=50)
		if(n%2) n=49;
		else n=48;
	f[0]=1;
	f[1]=1;
	for(int i=2;i<=n;++i)
		f[i]=f[i-1]+f[i-2];
	s[0]="0";
	s[1]="1";
	for(int i=2;i<=20;++i)
		s[i]=s[i-2]+s[i-1];
	if(n<=20){
		for(int i=l;i<=r;++i)
			putchar(s[n][i]);
		puts("");
		return 0;
	}
	solve(n,l,r);
	fclose(stdin); fclose(stdout);
	return 0;
}
原文地址:https://www.cnblogs.com/yjkhhh/p/9814351.html