##思路: 题目的主要信息:

  • 定义函数f(x)=xa+xa+1+...+xb1+xbf(x) = x^a + x^{a+1} +...+ x^{b-1} + x^bf(x)=xa+xa+1+...+xb1+xb
  • 已知nnnaaabbb,求f(n)%10000000033f(n)\%10000000033f(n)%10000000033

方法一:暴力解法(超时) 具体做法: 写一个循环算幂的函数,然后遍历aaabbb,将计算的幂结果相加并取模。

class Solution {
public:
    long long cal(int x, int i){ //计算x的i次幂
        long long res = 1;
        for(int j = 0; j < i; j++)
            res *= x;
        return res;
    }
    long long solve(int a, int b, int n) {
        long long res = 0;
        for(int i = a; i <= b; i++) //循环相加
            res = (res + cal(n, i)) % 10000000033;
        return res;
    }
};

复杂度分析:

  • 时间复杂度:O(b2a2)O(b^2-a^2)O(b2a2),内外循环加起来一共运算次数是a+a+1+a+2+...+b1+b=(a+b)(ba+1)/2a+a+1+a+2+...+b-1+b=(a+b)*(b-a+1)/2a+a+1+a+2+...+b1+b=(a+b)(ba+1)/2
  • 空间复杂度:O(1)O(1)O(1),常数空间

方法二:数列求和+快速幂+快速乘法+逆元 具体做法: 这道题的数据很大,我们不仅要考虑超时的问题,还应该考虑爆long long的问题,因此我们需要多次优化:

  • 对于相加运算次数,我们可以用数列求和解决
  • 对于幂运算次数,我们可以用快速幂解决
  • 对于爆long long的问题,我们可以用快速乘法,以及费马小定理的逆元解决
  1. 数列求和f(x)=xa+xa+1+...+xb1+xb=(xb+1xa)/(x1)f(x) = x^a + x^{a+1} +...+ x^{b-1} + x^b=(x^{b+1}-x^a)/(x-1)f(x)=xa+xa+1+...+xb1+xb=(xb+1xa)/(x1),这样一来我们就不用再循环相加了。

  2. 快速幂。如果我们要计算5105^{10}510,常规的算法是55=255*5=2555=25,然后再255=12525*5=125255=125,如此往下,一共是999次运算,即n1n-1n1次。但是我们可以考虑这样:55=255*5=2555=25(二次)、2525=62525*25=6252525=625(四次)、625625=...625*625=...625625=...(八次),这是一个二分的思维,运算次数缩减到了log2nlog_2nlog2n次,公式如下: 图片说明

  3. 快速乘法。直接计算xax^axa会超出long long的表示范围,因此我们可以考虑用加法来代替乘法,并在这其中取模。就比如ab=a(b1+b2+b3+...)a*b=a*(b_1+b_2+b_3+...)ab=a(b1+b2+b3+...),其中bib_ibi是数字bbb的二进制各位,假设a=5a=5a=5b=110101b=110101b=110101,我们有ab=a(1000001+100001+10000+1001+100+11)a*b=a*(100000*1+10000*1+1000*0+100*1+10*0+1*1)ab=a(1000001+100001+10000+1001+100+11),如下表所示可以换成加法运算并在加法中取模: 图片说明

  4. 逆元。为了计算(xb+1xa)/(x1)(x^{b+1}-x^a)/(x-1)(xb+1xa)/(x1)我们也要超出long long限制的问题,因为有取模的关系。对此有一个数学定理(费马小定理):如果ppp是一个质数,而整数xxx不是ppp的倍数,则有xp1%p1x^{p-1} \% p \equiv 1xp1%p1,我们取的模10000000033正是一个质数。上述公式两边同时除xxxxp2%p1/x%px^{p-2} \% p \equiv 1/x \% pxp2%p1/x%p,即(xb+1xa)/(x1)%mod(xb+1xa)%mod1/(x1)%mod(x^{b+1}-x^a)/(x-1) \% mod \equiv (x^{b+1}-x^a) \% mod * 1/(x-1) \% mod(xb+1xa)/(x1)%mod(xb+1xa)%mod1/(x1)%mod (xb+1xa)%mod(x1)mod2%mod\equiv(x^{b+1}-x^a) \% mod * (x-1)^{mod-2} \% mod (xb+1xa)%mod(x1)mod2%mod

class Solution {
public:
    long long mod = 10000000033;
    long long fast(long long x, long long y){ //快速乘法
        long long res = 0;
        x %= mod;
        y %= mod;
        while(y){
            if(y & 1){
                res += x; //加法代替乘法,防止爆long long
                if(res >= mod)
                    res -= mod;
            }
            y = y >> 1;
            x = x << 1;
            if(x >= mod)
                x -= mod;
        }
        return res;
    }
    long long Pow(long long x, long long y){ //快速幂
        long long res = 1;
        while(y){
            if(y & 1) //可以再往上乘一个
                res = fast(res, x); 
            x = fast(x, x); //叠加
            y = y >> 1; //减少乘次数
        }
        return res;
    }
    long long solve(int a, int b, int n){
        if(n == 0)
            return 0;
        if(n == 1) 
            return b - a + 1;
        long long res = (Pow(n, b + 1) - Pow(n, a) + mod) % mod; //数列求和
        long long temp = Pow(n - 1, mod - 2); //费马小定理求逆元
        return fast(res, temp);
    }
};

复杂度分析:

  • 时间复杂度:O((log2n)2)O((log_2n)^2)O((log2n)2),这里的n=max(b+1,a,mod2)n=max(b+1,a,mod-2)n=max(b+1,a,mod2),不管是快速幂还是快速乘法都是O(log2n)O(log_2n)O(log2n),这里嵌套使用
  • 空间复杂度:O(1)O(1)O(1),常数空间