牛客2020跨年场 E-牛牛的反函数 思维/打表找规律
牛牛定义了一个递归函数F(x),x为正整数且定义域范围$x \in [1,10^{18}]$
$ F(x) = \begin{cases} 1 & \text{ if } x=1 \\ F(x+1)+1 & \text{ if } x\neq1 \quad and \quad x%2=1 \\ F(x/2)+1 & \text{ if } x%2=0 \end{cases} $
现在牛牛想要你编写一个程序实现这个函数的反函数功能,也就是说我们输入一个正整数y$(y\in [1,10^{9}])$,你要找到范围在$[1,10^{18}]$内的正整数x,使得F(x)=y。
如果在$[1,10^{18}]$内不存在任何一个正整数x使得F(x)=y。请输出"-1"(不含引号)代表无解,如果有多个满足条件的x,你只用随便输出一个大小在$[1,10^{18}]$内的合法解即可
题解:
打表,可看出反函数最小解的规律如下
$F^{-1}(2k)=2^k+1$
$F^{-1}(2k-1)=2^k+2$
判断最小解是否在1e18范围内即可,注意特判1的情况
#include<iostream> #define maxx 1000000000000000000ll #define LL long long using namespace std; bool mapp[1000005]; int a[1000005]; int gcd(int a,int b){ if(b==0)return a; else return gcd(b,a%b); } int main(){ int n; scanf("%d",&n); while(n--){ int x; scanf("%d",&x); if(x==1){ printf("1\n"); continue; } LL ans=1; for(int i=1;i<=(x-1)/2;i++){ ans*=2; if(ans>maxx){ printf("-1\n"); goto A; } } if(x%2==0){ if(ans+1>maxx)printf("-1\n"); else printf("%lld\n",ans+1); }else{ if(ans+2>maxx)printf("-1\n"); else printf("%lld\n",ans+2); } A:; } return 0; }