题意整理
- 给定函数
以及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.复杂度分析
- 时间复杂度:方法一需要计算所有指数的累加和次幂运算,本方法利用费马小定理和等比数列公式,只需要计算
次幂运算,所以时间复杂度为
。
- 空间复杂度:需要额外常数级别的空间,所以空间复杂度为
。

京公网安备 11010502036488号