【问题标题】:Optimal Solution of the code so that It can perform computation upto 10^18代码的最佳解决方案,使其可以执行高达 10^18 的计算
【发布时间】:2019-09-14 00:25:55
【问题描述】:

约束 1≤T≤10^5 1≤N≤10^18

斐波那契数列 F0,F1,... 是一个特殊的非负整数无限序列,其中 F0=0,F1=1,对于每个整数 n≥2,Fn=Fn-1+Fn-2。

考虑前 N 个斐波那契数的最后一个十进制数字的序列 D,即 D=(F0%10,F1%10,…,FN−1%10)。现在,您应该执行以下过程:

令 D=(D1,D2,…,Dl)。 如果 l=1,则过程结束。 创建一个新序列 E=(D2,D4,...,D2⌊l/2⌋)。换句话说,E 是通过从 D 中删除所有奇数索引元素创建的序列。 将 D 更改为 E。

说明 示例案例 1:前 N 个斐波那契数是 (0,1,1,2,3,5,8,13,21)。序列D是(0,1,1,2,3,5,8,3,1)→(1,2,5,3)→(2,3)→(3)。

到目前为止我做了什么
    #include<iostream>
    #include<vector>
    using namespace std;
    #define m 10
void multiply(long long f[][2], long long g[][2])
{
    long long a = (f[0][0] * g[0][0] + f[0][1] * g[1][0]) % m;
    long long b = (f[0][0] * g[0][1] + f[0][1] * g[1][1]) % m;
    long long c = (f[1][0] * g[0][0] + f[1][1] * g[1][0]) % m;
    long long d = (f[1][0] * g[0][1] + f[1][1] * g[1][1]) % m;

    f[0][0] = a;
    f[0][1] = b;
    f[1][0] = c;
    f[1][1] = d;
}
void power(long long f[2][2], long long n)
{
    long long g[2][2] = { {1,1},{1,0} };
    if (n == 0 || n == 1)
        return;
    power(f, n / 2);
    multiply(f, f);

    if (n % 2 == 1)
        multiply(f, g);
}
long long fib(long long n)
{
    long long f[2][2] = { {1,1},{1,0} };
    if (n == 0)
        return 0;
    power(f, n - 1);
    return f[0][0] % m;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    unsigned int t;
    std::cin >> t;
    while (t--) {
        long long int td;
        std::cin >> td;
        vector<long long int> d;
        unsigned long long int temp;
        for (unsigned long long int i = 0;i < td;i++) {
            d.push_back(fib(i) % m);
        }
        if (d.size() == 1) {
            cout << d[0] << endl;
        }
        else if (d.size() == 2 || d.size() == 3) {
            cout << d[1] << endl;
        }
        else {
            vector<long long int> e;
            long long int si = d.size();
            while (si != 1) {
                for (long long i=1;i<si;i=i+2) {
                        e.push_back(d[i]);
                }
                d = e;
                e.clear();
                si = d.size();
            }
            cout << d[0] << " ";
        }
        d.clear();
    }
    return 0;
}

【问题讨论】:

  • 听起来你有一些有用的东西,但你想让它更好地工作。 Give a read through this 看看你的问题是否更适合代码审查。
  • 如果你解决了数学问题,也许有人可以帮助你实现它?
  • @user4581301 我已经更正了!
  • @TedLyngmo 一次,它工作得很好,但是对于 n 个连续整数,它的时间限制超过了
  • 请注意,如此定义的 D 必须在 10^2 = 100 个条目下循环。为什么?每个元素都是一个斐波那契数 mod 10,所以 D 的元素也满足 D(n+2) = D(n+1) + D(n);一旦连续两个数字重复,则循环必须重复;并且只有 10x10=100 个可能的两位十进制数字字符串。弄清楚它是如何循环的,你可以走捷径,比如立即说出索引 10^100 处的元素是什么

标签: c++ algorithm vector


【解决方案1】:
 #include<iostream>
 #include<vector>
 using namespace std;
 int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    // the last digits of the fibonnacci sequence repeat at 60.
    // let's just get them all
    int lastDigits[60];
    lastDigits[0] = 0;
    lastDigits[1] = 1;
    for (int i=2;i<60;i++) {
        lastDigits[i] = (lastDigits[i-2]+lastDigits[i-1]) % 10;
    }

    unsigned int t;
    std::cin >> t; //number of test cases
    while (t--) {
        long long int td;
        std::cin >> td;  //next case

        // after repeatedly removing even-indexed (zero-based) items, the
        // original index of the last remaining item will be the highest
        // 2^n - 1 that fits.  We can calculate this directly
        td >>= 1;
        td |= td>>32;
        td |= td>>16;
        td |= td>>8;
        td |= td>>4;
        td |= td>>2;
        td |= td>>1;

        cout << lastDigits[(int)(td%60)] << endl;
    }
    return 0;
}

【讨论】:

    猜你喜欢
    • 2016-11-14
    • 1970-01-01
    • 2021-10-13
    • 1970-01-01
    • 2022-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-26
    相关资源
    最近更新 更多