【校内模拟】数列

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

这是一套模拟题的\(T1\)

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

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

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

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

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

题解:

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

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

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

\(n\leq 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;
}
posted @ 2018-10-19 09:56  yjk  阅读(137)  评论(0编辑  收藏  举报