SPOJ DIVSUM2 PollardRho 康某

大意:给出一个数,求他的所有因子的和(不包括自己)

首先,先算上他自己,问题转化为求所有因子的和

根据唯一分解定理,设数为N,则质因子为P1P2...PK,指数设为A1A2...AK

则所有因子,则是P1位指数取【0,A1】,P2位取【0,A2】…………

譬如20 = 2 ^2 * 5,则因子为 1(2^0 * 5^0),2(2^1 * 5 * 0),4(2 ^ 2 * 5 ^ 0),5(2^0 * 5 ^ 1),10(2^1 * 5 ^ 1),20(2^2* 5 ^ 1)

提取一下 = 2^0 *(5 ^ 0 + 5 ^ 1) + 2^1 *(5 ^ 0 + 5 ^ 1) + 2^2 *(5 ^ 0 + 5 ^ 1)

= (2 ^ 0 + 2 ^ 1 + 2 ^ 2) * (5 ^ 0 + 5 ^ 1) = 42

挺对……于是公式可以得出……就是每个因子等比序列求和一下,然后求乘积得到所有因子相加的和,最后减去N自己即可……

问题在于怎么质因子分解……这个数很大,很难做……于是,我们要使用 PollardRho 算法……

另外有一点要注意……Java不是没有函数传地址……Java相当于传的是个Vector* ret,如果你想修改他,ret = XXX 是没戏的…… 而ret.set(XXX)是正解……

见第33行……

分解之后,排序,统计即可

 1 import java.math.BigInteger;
 2 import java.security.SecureRandom;
 3 import java.io.*;
 4 import java.util.*;
 5 
 6 
 7 
 8 class PollardRho {
 9     private final static BigInteger ZERO = new BigInteger("0");
10     private final static BigInteger ONE  = new BigInteger("1");
11     private final static BigInteger TWO  = new BigInteger("2");
12     private final static SecureRandom random = new SecureRandom();
13 
14     public static BigInteger rho(BigInteger N) {
15         BigInteger divisor;
16         BigInteger c  = new BigInteger(N.bitLength(), random);
17         BigInteger x  = new BigInteger(N.bitLength(), random);
18         BigInteger xx = x;
19 
20         // check divisibility by 2
21         if (N.mod(TWO).compareTo(ZERO) == 0) return TWO;
22 
23         do {
24             x  =  x.multiply(x).mod(N).add(c).mod(N);
25             xx = xx.multiply(xx).mod(N).add(c).mod(N);
26             xx = xx.multiply(xx).mod(N).add(c).mod(N);
27             divisor = x.subtract(xx).gcd(N);
28         } while((divisor.compareTo(ONE)) == 0);
29 
30         return divisor;
31     }
32 
33     public static void factor(BigInteger N, Vector<Long> ret) {
34         if (N.compareTo(ONE) == 0) return;
35         if (N.isProbablePrime(20)) { ret.add(N.longValue()); return; }
36         BigInteger divisor = rho(N);
37         factor(divisor,ret);
38         factor(N.divide(divisor),ret);
39     }
40 }
41 
42 class Main {
43     public static void main(String args[]) {
44         new Main().work();
45     }
46 
47     void factor(int n, Vector<Long> ret) {
48     }
49 
50     void work() {
51         try {
52             BufferedReader in = new BufferedReader(
53                     new InputStreamReader(System.in));
54             int nn = Integer.parseInt(in.readLine());
55             while (nn-- > 0) {
56                 long n = Long.parseLong(in.readLine());
57                 Vector<Long> ret = new Vector<Long>();
58                 PollardRho.factor(BigInteger.valueOf(n),ret);
59                 Collections.sort(ret);
60                 // System.err.println(ret);
61 
62                 Long ans = 1L;
63                 for (int i = 0; i < ret.size(); i++) {
64                     Long pow = 1L;
65                     Long sum = 1L;
66                     for (int j = i; j < ret.size() && ret.get(j).equals(ret.get(i));j++) {
67                         pow *= ret.get(j);
68                         sum += pow;
69                         i = j;
70                     }
71                     // System.err.printf("%d %d\n",pow,sum);
72                     ans *= sum;
73                 }
74                 System.out.println(ans - n);
75             }
76         } catch (Exception e) {}
77     }
78 }
原文地址:https://www.cnblogs.com/sweetsc/p/2580991.html