【簡要題意】有兩個數列{x},{y},滿足數論遞推式:
現在給定n,求m使得
如果輸出大於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 | ··· | ··· |
發現有通項公式:
由於指數函數在R上是單調函數,所以得到結論:
由於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);
}