大数模运算(POJ 1845)
http://blog.sina.com.cn/s/blog_6635898a0100omcn.html
直接抄过来了(不好意思)
题意:求A^B的所有约数之和 Mod 9901。
思路:大数模运算。两个最基本公式:(A*B)%C = ((A%C)*(B%C))%C 和 (A+B)%C = ((A%C)+(B%C))%C 。用__int64的原因为 n = cnt[i] * B (cnt[i]为A第i个素因子的个数)可能会超int。
1: 对A进行素因子分解得
A = p1^a1 * p2^a2 * p3^a3 *...* pn^an.
故 A^B = p1^(a1*B) * p2^(a2*B) *...* pn^(an*B);
2:A^B的所有约数之和为:
sum = [1+p1+p1^2+...+p1^(a1*B)] * [1+p2+p2^2+...+p2^(a2*B)] *...* [1+pn+pn^2+...+pn^(an*B)].
如 200 = 2^3 * 5^2 : sum(200) = [1 + 2 + 4 + 8] * [1 + 5 + 25].
3: 求等比数列1+pi+pi^2+pi^3+...+pi^n可以由递归形式的二分求得:(模运算不能用等比数列和公式!(乘法逆元))
若n为奇数,一共有偶数项,则:
1 + p + p^2 + p^3 +...+ p^n
= (1+p^(n/2+1)) + p * (1+p^(n/2+1)) +...+ p^(n/2) * (1+p^(n/2+1))
= (1 + p + p^2 +...+ p^(n/2)) * (1 + p^(n/2+1))
如:1 + p + p^2 + p^3 + p^4 + p^5 = (1 + p + p^2) * (1 + p^3)
若n为偶数,一共有奇数项,则:
1 + p + p^2 + p^3 +...+ p^n
= (1+p^(n/2+1)) + p * (1+p^(n/2+1)) +...+ p^(n/2-1) * (1+p^(n/2+1)) + p^(n/2)
= (1 + p + p^2 +...+ p^(n/2-1)) * (1+p^(n/2+1)) + p^(n/2);
如:1 + p + p^2 + p^3 + p^4 = (1 + p) * (1 + p^3) + p^2
import java.io.*; import java.util.*; import java.math.*; public classMain { static final int MOD = 9901; int a[], b[], len, A; long B; long Pow(long p, long n) { long res = 1; while (n > 0) { if ((n & 1) > 0) res = (res * p) % MOD; n >>= 1; p = (p * p) % MOD; } return res; } long Sum(long p, long n) { if (n == 0) return 1; if ((n & 1) > 0) return ((1 + Pow(p, n / 2 + 1)) * Sum(p, n / 2)) % MOD; else return ((1 + Pow(p, n / 2 + 1)) * Sum(p, n / 2 - 1) + Pow(p, n / 2)) % MOD; } void run() { A = cin.nextInt(); B = cin.nextInt(); int n = (int) Math.sqrt(A), tn = A; a = new int[n + 1]; b = new int[n + 1]; len = 0; for (int i = 2; i <= n && i <= tn; i++) { if (tn % i == 0) { a[len] = i; while (tn % i == 0) { tn /= i; b[len]++; } len++; } } if (tn > 1) { a[len] = tn; b[len++] = 1; } long ans = 1; for (int i = 0; i < len; i++) ans = (ans * Sum(a[i], b[i] * B)) % MOD; System.out.println(ans); } public static void main(String[] args) { Mainsolved = new Main(); solved.run(); } // static InputStream inputStream = System.in; // static InputReader cin = new InputReader(inputStream); Scannercin = new Scanner(new BufferedInputStream(System.in)); } classInputReader { private InputStreamstream; private byte[] buf = new byte[1024]; private int curChar; private int numChars; public InputReader(InputStreamstream) { this.stream = stream; } public int read() { if (numChars == -1) return -1; //throw new InputMismatchException(); if (curChar >= numChars) { curChar = 0; try { numChars = stream.read(buf); } catch (IOExceptione) { throw new InputMismatchException(); } if (numChars <= 0) return -1; } return buf[curChar++]; } public int nextInt() { int c = read(); if (c == -1) return -1; while (isSpaceChar(c)) c = read(); int sgn = 1; if (c == '-') { sgn = -1; c = read(); } int res = 0; do { if (c < '0' || c > '9') throw new InputMismatchException(); res *= 10; res += c - '0'; c = read(); } while (!isSpaceChar(c)); return res * sgn; } public Stringnext() { StringBuilderstr = new StringBuilder(); int ch; while (isSpaceChar(ch = read())); if (ch == -1) return null; do { str.appendCodePoint(ch); } while (!isSpaceChar(ch = read())); return str.toString(); } public static boolean isSpaceChar(int c) { return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1; } public char nextCharacter() { int c = read(); while (isSpaceChar(c)) c = read(); return (char) c; } }