牛客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;
}

 

posted @ 2021-01-01 10:03  Isakovsky  阅读(141)  评论(0编辑  收藏  举报