數列

【簡要題意】有兩個數列{x},{y},滿足x0=y0=1x_0=y_0=1數論遞推式:
xn=xn12+xn1,yn=yn121+2yn1,(n1)x_n=\frac{x_{n-1}}{2+x_{n-1}},y_n=\frac{y^2_{n-1}}{1+2y_{n-1}},(n≥1)
現在給定n,求m使得xm=ynx_m=y_n
如果輸出大於maxlongint輸出其位數

【分析】
先打表找規律,有:

0 1 2 3 4 5
x 1 1/3 1/7 1/15 1/31 1/63
y 1 1/3 1/15 1/225 ··· ···

發現有通項公式:
xn=2n+11,yn=22n1,(n0)x_n=2^{n+1}-1,y_n=2^{2^n}-1,(n≥0)
由於指數函數在R上是單調函數,所以得到結論:
m=2n1m=2^n-1
由於2的冪個位爲2、4、8、6,所以不用考慮退位。
n<=31時直接左移輸出即可,否則手動模擬科學計數法(不在乎精度缺失,逃)

【code】

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
struct node{
	long double num;
	LL len;
};
node operator*(node x,node y){
	node ret;
	ret.num=x.num*y.num;
	ret.len=x.len+y.len;
	while(ret.num>=10) ret.num=ret.num/10,ret.len++;
	return ret;
}
LL n,m;
inline LL pow(node x,LL p){
	node ret=(node){1,0};
	while(p>0){
		if(p&1) ret=ret*x;
		x=x*x,p=p>>1;
	}
	return ret.len+1;
}
int main(){
	freopen("math.in","r",stdin);
	freopen("math.out","w",stdout);
	cin>>n;
	if(n<=31) cout<<(1<<n)-1<<endl;
	else cout<<pow((node){2,0},n)<<endl;
	return 0;
}

還有一種做法是直接log運算,也放一下代碼:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int read(){
	int u=0,f=1;char c=getchar();
	while(c<'0'||c>'9') f=(c=='-'?-1:1),c=getchar();
	while(c>='0'&&c<='9') u=(u<<1)+(u<<3)+c-'0',c=getchar();
	return u*f;
}
int n;
int main(){
	freopen("math.in","r",stdin);
	freopen("math.out","w",stdout);
	n=read();
	if(n<=31) cout<<(1ll<<n)-1;
	else cout<<(int)(n*(log(2)/log(10))+1);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章