JAVA计算3^n-3*2^n+;3.

JAVA计算3^n-3*2^n+;3.,java,algorithm,data-structures,puzzle,Java,Algorithm,Data Structures,Puzzle,我正在计算 ((3^n)-(3*(2^n))+3)对于1问题是独立于JAVA的,对于大型b,您需要高效地找到a^b。您可以通过使用模幂运算来实现这一点,复杂性是O(log(b)) long long power(long long a,long long b) { if(b==0)return 1; long long ans=power(a,b/2); ans=(ans*ans)%1000000007; if(b%2)an

我正在计算

((3^n)-(3*(2^n))+3)对于1问题是独立于JAVA的,对于大型b,您需要高效地找到a^b。您可以通过使用模幂运算来实现这一点,复杂性是O(log(b))

  long long power(long long a,long long b)
  {
        if(b==0)return 1;
        long long ans=power(a,b/2);
        ans=(ans*ans)%1000000007;
        if(b%2)ans=(ans*a)%1000000007;
        return ans;
  }
以上是在c/c++中,同样的逻辑可以在JAVA中扩展。
编辑

现在,当您需要为1执行此操作时,您可以使用BigInteger类以获得更好的精度。 乙二醇


*如果在for循环中使用它,您可能会从预计算中获得一些优势,因为每一次
n
都可能使用先前
n-1
计算的结果。例如3^n可以计算为3^(n-1)*3

您面临两个问题,这两个问题都可以通过使用BigInteger来解决。首先,BigInteger能够保存您的值,其次它已经实现了一种执行模幂运算的方法:

BigInteger  modPow(BigInteger exponent, BigInteger m)
它返回一个BigInteger,其值为(此^指数mod m)


另一方面,如果您感兴趣,为什么它不起作用(即速度太慢),我建议您在下面的文章中解释高效整数指数运算

避免使用大整数和从头开始计算幂,这是一种幼稚而低效的方法

使用模运算进行增量运算

保留两个整数变量,其中包含
A的值ₙ:= 3.ⁿ 100000007模块
Bₙ:= 3×2ⁿ mod 100000007

更新是显而易见的:
Aₙ₊ₗ= 3×Aₙ 100000007模块
Bₙ₊ₗ= 2×Bₙ mod 100000007

对于模运算,我建议使用比较而不是
%

幸运的是
2×100000007
适合32位有符号整数。但不是
3×100000007
,因此我建议将3乘以两个加法

因此,您所要实现的就是模加减整数
100000007

私有静态整数和(整数x,整数y)
{
返回x>=100000007-y?x-(100000007-y):x+y;
}
专用静态int sub(int x,int y)
{
返回x对于(n=1;n这是你的家庭作业吗?你需要的计算精度有多高?你似乎需要绝对精度的整数数学——在这种情况下,你的代码根本不可能工作:你使用双精度,它的精度位远低于你需要存储的3^109位(大约173位)…你需要在使用Java之前算出你的数学。@BrunoReis它都是模100000007!想要最快的解决方案吗?使用一个预先计算的表;pDo你的意思是
N这也太慢了-比double慢得多。-1这对速度没有帮助,因为它必须为1@laune计算,现在它将是O(log(N))您使用的是
O(N Log(N))
方法,其中
O(N)
很容易实现。@migdal:请仔细阅读。计算所有
N
会使其成为
O(N Log(N))
。毕竟,问题有点含糊不清。如果要为范围
[1109]中的单个值返回值
,然后将函数制表是一种非常好的方法,正如FabioMarcolini所说;它是
O(1)
。如果要计算所有值(例如构建此表:),那么可以推荐迭代
O(N)
方法。BigInteger的实现方式,我怀疑这也太慢了。遗憾的是,我们不知道时间限制。1)它的实现非常有效2)时间限制是1秒,在我的机器上,这一时间足以使它下降100倍以上。对于多精度整数,BigInteger并不是最有效的实现。与其他技术相比,它有一些优势,但最大速度不是其中之一。尽管一秒钟可能就足以解决这个问题,如果编码足够好的话。它适合
long
,但是。做得很好,尽管编码方式伤害了我的眼睛。@mare以什么方式?你如何从少数几行程序片段中判断“风格”?有sun/oracle编码惯例,例如方法名称应以小写开头,变量名称也应如此等等。大多数java程序员至少坚持这些,所以说这伤害了我的眼睛可能太苛刻了,我想换一种说法:“对于java代码段来说,这是一种不常见的风格”@learner:你怎么能显示一个大于100000007的数字并声称这是一个正确的答案?
  long long power(long long a,long long b)
  {
        if(b==0)return 1;
        long long ans=power(a,b/2);
        ans=(ans*ans)%1000000007;
        if(b%2)ans=(ans*a)%1000000007;
        return ans;
  }
private static final BigInteger TWO = new BigInteger("2");
private static final BigInteger THREE = new BigInteger("3");

//input n, m (modulo)
public static BigInteger getResult(BigInteger n, BigInteger m) {
    BigInteger a = THREE.modPow(n, m);
    BigInteger b = TWO.modPow(n, m);

    return a.subtract(THREE.multiply(b)).add(THREE).mod(m);

}
BigInteger  modPow(BigInteger exponent, BigInteger m)