• UVA 701 The Archeologists' Dilemma


    UVA_701

        看了别人的解题报告之后,发现可以枚举剩余数字的位数,我们不妨设其为k,那么我们会得到不等式,N*10^k<=2^E<N*10^k,化简之后就可以得到log2(N)+k*log2(10)<=E<log2(N+1)+k*log2(10),我们设左右边界为a、b的话,问题就等价于如果在枚举k的过程中出现了[a,b)内有一个整数点的话,那个值就是E。

        首先来讲,由于b-a=log2((N+1)/N)<log2(2)=1,所以区间内如果出现整数点的话最多只有一个。接着,我们要解决的问题就是,随着我们不断地枚举k,是否一定在某一刻内出现[a,b)内有一个整数点的情况呢?

        对于这个问题我是这样想的,实际我们就是希望b-a这么宽的区间能够覆盖某个整数点,而对于k*log2(10)来讲,由于log2(10)是一个无理数,因此k*log2(10)-[k*log2(10)]不会有一个固定的整数周期,甚至不会出现两个不同的k使得它们的的值相等,这点可以用反证法证明。再加之k是整数,感觉上这个表达式的值应该在[0,1)之内分布的比较均匀,这样我们多次枚举之后,应该会出现某一时刻使得b-a这么宽的区间覆盖一个整数点。

        当然,前面只是感觉,也只是说理论上可以找到,但我们不妨分析一下b-a的取值,在最坏的情况下,区间长度只有7*10^(-10)左右,即便前面所说的表达式的值分布得再均匀,1s也不过能细化到10^(-8),也就是说大概能保证区间[a,b)长度是10^(-8)左右的数据能在1s之内找到解,这远远不能满足最坏的情况。不信的话可以把这种枚举的程序出一些9位数的数据试一下,就会发现程序跑得很慢,因为通常找到的解是8位数以上的。

        总而言之,我现在还没找到很“有效”的算法,之所以枚举能过,应该也是数据出得比较小的缘故。

        后来听YTQ说,由于这个题目是2000年出的,所以可能题目中所指的整数E是在65536之内的,这样的话枚举范围就很小了。

    #include<stdio.h>
    #include<string.h>
    #include<math.h>
    long long int N;
    char b[20];
    void solve()
    {
    int k, x, y;
    sprintf(b, "%d", N);
    for(k = strlen(b) + 1;; k ++)
    {
    x = (long long int)(log2(N) + k * log2(10));
    y = (long long int)(log2(N + 1) + k * log2(10));
    if(x != y)
    {
    printf("%d\n", y);
    break;
    }
    }
    }
    int main()
    {
    while(scanf("%lld", &N) == 1)
    {
    solve();
    }
    return 0;
    }


  • 相关阅读:
    12迭代器
    11(2)Vector(向量)
    11(1) LinkList ---链表
    11集合(Collection<E>) Arraylist
    10异常
    乘法计算过程的模拟
    10 Date详解
    详细的OA系统学习
    8 math类
    Java开发中的23种设计模式详解
  • 原文地址:https://www.cnblogs.com/staginner/p/2293717.html
Copyright © 2020-2023  润新知