大意:给出一个数,求他的所有因子的和(不包括自己)
首先,先算上他自己,问题转化为求所有因子的和
根据唯一分解定理,设数为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 }