如何在java中生成n个?

时间:2014-08-16 14:57:03

标签: java algorithm math biginteger

我遇到了一个算法,我需要生成n个数字'1',其中n<=10^16n>=1。我使用for loopBigInteger中成功生成了n个,因为long以及string无法保留此值。但问题是时间限制为4 sec4 sec需要的时间超过n>10^5。这显然是在O(n)中产生的。我认为没有必要使用相应的代码。我发现很多网站但找不到任何解决方案。任何更好的算法都会有所帮助。谢谢。
编辑:这是一个拼图问题,nm输入,我需要打印111...(n times) mod m,其中限制为1≤N≤10^162≤M≤10^9。例如,
假设n=3&amp; m=3然后打印111%3,其等于0。假设n=5&amp; m=18然后打印11111%18,等于5
如果您使用longString,则会抛出NumberFormatException我将其更改为BigInteger然后异常消失。

public static void main(String[] ar){
    Scanner in= new Scanner(System.in);
    int t=in.nextInt();
    while(t-->0){
        BigInteger n=new BigInteger(Long.toString(in.nextLong()));
        BigInteger m=new BigInteger(Long.toString(in.nextLong()));
        BigInteger s=new BigInteger("1");
        for(long i=1;i<n.intValue();i++)
            s = s.multiply(new BigInteger("10")).add(new BigInteger("1"));
        System.out.println(s.mod(m));
}

enter image description here

2 个答案:

答案 0 :(得分:5)

如果S(n)是n个,则这些方程式成立:

S(1) = 1
S(2n) = S(n) * (10^n + 1)
S(n+1) = S(n) * 10 + 1

您可以使用这两个重复(模m)来计算S(n)模数。

S(n) % m =
   1                                          [if n is 1]
   ((S(n/2) % m) * ((10^{n/2} % m) + 1)) % m  [if n is even]
   ((S(n-1) % m)) * 10 + 1) % m               [if n is odd]

你仍然需要能够有效地计算10 ^ n%m,虽然这可以通过使用求幂进行平方来完成,但也可以使用10 ^ n = 9 * S(n)+1的事实。 / p>

使用10 ^ n和S(n)之间的后一种关系,可以得到这组方程式,这些方程式很容易编码为递归(或迭代)程序:

S(n) % m =
   1                                 [if n is 1]
   x*(9x+2) % m where x = S(n/2)%m   [if n is even]
   ((S(n-1) % m) * 10 + 1) % m       [if n is odd]

在Python中,这给我的笔记本电脑上的n = 10 ^ 16,m = 10 ^ 9,0.017s的运行时间,这完全在4s的最后期限内。

答案 1 :(得分:1)

我有一个想法,可以帮助您以某种方式优化您的代码。

以下是我的数学笔记的直接翻译(带有斜体字的注释),所以如果你发现不清楚的地方,请指出。

如何查找数字是否可被37 整除(在您的情况下为m)

我们有以下

10 ^0≡1(mod 37)
10 ^1≡10(mod 37)
10 ^2≡26(mod 37)
10 ^3≡1(mod 37)

基本上这样做,直到你看到重复

所以现在如果我们想看看数字是否可被37整除(或剩下的是什么),我们用上面得到的系数代替10的幂。这意味着 a * 10 ^ 3 + b * 10 ^ 2 + c * 10 ^ 1 + d mod 37 = a * 1 + b * 26 + c * 10 + d mod 37.

实数

的示例

(数字为10 ^ 16位1)mod 37 =(1 + 26 + 10 + 1)* 10 ^ 16/4 mod 37 = 21

您可以重复此过程一次,每次执行此操作时,结果数字按比例缩小(10 ^ 16位数字缩小为16位数字)