【简要题意】有两个数列{x},{y},满足
x
0
=
y
0
=
1
x_0=y_0=1
x0=y0=1数论递推式:
x
n
=
x
n
−
1
2
+
x
n
−
1
,
y
n
=
y
n
−
1
2
1
+
2
y
n
−
1
,
(
n
≥
1
)
x_n=\frac{x_{n-1}}{2+x_{n-1}},y_n=\frac{y^2_{n-1}}{1+2y_{n-1}},(n≥1)
xn=2+xn−1xn−1,yn=1+2yn−1yn−12,(n≥1)
现在给定n,求m使得
x
m
=
y
n
x_m=y_n
xm=yn
如果输出大于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 | ··· | ··· |
发现有通项公式:
x
n
=
2
n
+
1
−
1
,
y
n
=
2
2
n
−
1
,
(
n
≥
0
)
x_n=2^{n+1}-1,y_n=2^{2^n}-1,(n≥0)
xn=2n+1−1,yn=22n−1,(n≥0)
由于指数函数在R上是单调函数,所以得到结论:
m
=
2
n
−
1
m=2^n-1
m=2n−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);
}