题意整理

  • 给定函数以及a、b的值。
  • ,结果对10000000033取余。

方法一(模拟)

1.解题思路

首先当n为0时,直接返回0。然后模拟题目给的函数进行计算,为了防止溢出,乘方运算需要使用大数快幂法。由于测试数据较大,这种方法运行超时。

2.代码实现

import java.util.*;
import java.math.BigInteger;

public class Solution {
    /**
     * 
     * @param sa string字符串 
     * @param sb string字符串 
     * @param n int整型 
     * @return long长整型
     */
    //定义要用到的一些常量
    final BigInteger MOD=new BigInteger("10000000033");
    final BigInteger ZERO=new BigInteger("0");
    final BigInteger ONE=new BigInteger("1");
    final BigInteger TWO=new BigInteger("2");

    public long solve (String sa, String sb, int n) {
        //特殊情况处理
        if(n==0) return 0L;
        BigInteger res=ZERO;
        //定义函数计算要用到的大数
        BigInteger a=new BigInteger(sa);
        BigInteger b=new BigInteger(sb);
        BigInteger x=new BigInteger(String.valueOf(n));
        //模拟函数计算
        for(BigInteger i=a;i.compareTo(b)==-1;i=i.add(ONE)){
            res=res.add(((i.add(ONE).mod(MOD)).multiply(fastpow(x,i)).mod(MOD))).mod(MOD);
        }

        return res.longValue();
    }

    //大数快幂法
    private BigInteger fastpow(BigInteger n,BigInteger k){
        BigInteger res=ONE;
        while(!k.equals(ZERO)){
            //如果是奇数,res需要乘以基数n
            if(k.mod(TWO).longValue()==1L){
                res=res.multiply(n).mod(MOD);
            }
            //每次n作平方处理,k减半
            n=n.multiply(n).mod(MOD);
            k=k.divide(TWO);
        }
        return res;
    }
}

3.复杂度分析

  • 时间复杂度:大数快幂法的时间复杂度是,总共需要进行次幂运算,所以时间复杂度为
  • 空间复杂度:需要额外常数级别的空间,所以空间复杂度为

方法二(等比数列公式+费马小定理)

1.解题思路

已知,等式两边同时乘以x得:,然后错位相减,可得:,可以发现,右边多项式的前项是等比数列。
利用等比数列公式,化简之后的函数是:,然后根据费马小定理,,所以两边同时除以再互换位置,得:,于是,可转化为

动图展示(快幂法):
图片说明

2.代码实现

import java.util.*;
import java.math.BigInteger;

public class Solution {
    /**
     * 
     * @param sa string字符串 
     * @param sb string字符串 
     * @param n int整型 
     * @return long长整型
     */
    //定义要用到的一些常量
    final BigInteger MOD=new BigInteger("10000000033");
    final BigInteger ZERO=new BigInteger("0");
    final BigInteger ONE=new BigInteger("1");
    final BigInteger TWO=new BigInteger("2");

    public long solve (String sa, String sb, int n) {
        //特殊情况处理
        if(n==0) return 0L;
        BigInteger res=ZERO;
        //定义函数计算要用到的大数
        BigInteger a=new BigInteger(sa);
        BigInteger b=new BigInteger(sb);
        BigInteger x=new BigInteger(String.valueOf(n));

        //n等于1时,只需计算a+1到b之间所有数字的和
        if(n==1){
            return a.add(b).mod(MOD).add(ONE).mod(MOD)
                    .multiply(b.subtract(a).mod(MOD))
                    .divide(TWO).mod(MOD).longValue();
        }

        //x-1对应的大数
        BigInteger div=x.subtract(ONE).add(MOD).mod(MOD);
        //(bx-b-1)*x^b对应的大数
        BigInteger f1=b.multiply(x).subtract(b).subtract(ONE).add(MOD).mod(MOD)
                       .multiply(fastpow(x,b)).mod(MOD);
        //(ax-a-1)*x^a对应的大数
        BigInteger f2=a.multiply(x).subtract(a).subtract(ONE).add(MOD).mod(MOD)
                       .multiply(fastpow(x,a)).mod(MOD);

        //推导出来的公式
        res=inv(f1.subtract(f2).add(MOD).mod(MOD),div.pow(2).mod(MOD));
        return res.longValue();
    }

    //利用费马小定理重写大数除法运算,防止运算不准
    private BigInteger inv(BigInteger a,BigInteger b){
        return a.multiply(fastpow(b,MOD.subtract(TWO))).mod(MOD);
    }

    //大数快幂法
    private BigInteger fastpow(BigInteger n,BigInteger k){
        BigInteger res=ONE;
        while(!k.equals(ZERO)){
            //如果是奇数,res需要乘以基数n
            if(k.mod(TWO).longValue()==1L){
                res=res.multiply(n).mod(MOD);
            }
            //每次n作平方处理,k减半
            n=n.multiply(n).mod(MOD);
            k=k.divide(TWO);
        }
        return res;
    }
}

3.复杂度分析

  • 时间复杂度:方法一需要计算所有指数的累加和次幂运算,本方法利用费马小定理和等比数列公式,只需要计算次幂运算,所以时间复杂度为
  • 空间复杂度:需要额外常数级别的空间,所以空间复杂度为