求助dalao们,51nod1170实在是不会了,有没有大佬讲一下,有兴趣的可以告诉我,我提供AC代码。
using System; using System.Collections.Generic; using System.Diagnostics; using System.Numerics; namespace Problem51Nod { class Program { public static void Main(String[] args) { //BigInteger m = BigInteger.Pow(5, 143) - 1; //BigInteger n = BigInteger.Pow(2, 331) + 1; //int k = 100; BigInteger m = BigInteger.Parse(Console.ReadLine()); BigInteger n = BigInteger.Parse(Console.ReadLine()); int k = Convert.ToInt32(Console.ReadLine()); //Stopwatch timer = new Stopwatch(); //timer.Start(); Console.WriteLine(Cmn(m, n, k)); //timer.Stop(); //Console.WriteLine(timer.Elapsed); } static BigInteger[][] PowerTable = new BigInteger[6][]; static List<BigInteger[][]>[] PreTable = new List<BigInteger[][]>[6]; static BigInteger[,] CMatrix; static void InitCMatrix(int l) { CMatrix = new BigInteger[l + 1, l + 1]; for (int i = 0; i <= l; i++) CMatrix[i, 0] = CMatrix[i, i] = 1; for (int i = 2; i <= l; i++) for (int j = 1; j * 2 <= i; j++) CMatrix[i, j] = CMatrix[i, i - j] = CMatrix[i - 1, j - 1] + CMatrix[i - 1, j]; } static void InitPowerTab(int l, int p) { PowerTable[p] = new BigInteger[l + 1]; PowerTable[p][0] = 1; for (int j = 1; j < PowerTable[p].Length; j++) PowerTable[p][j] = PowerTable[p][j - 1] * p; } static void InitData(int l, BigInteger max, int p) { PreTable[p] = new List<BigInteger[][]>(); BigInteger[] pre = MulTo(l, p); BigInteger[,] cMatrix = new BigInteger[l + 1, l + 1]; for (int i = 0; i <= l; i++) for (int j = 0; j <= i; j++) cMatrix[i, j] = CMatrix[i, j]; int power = 1; for (BigInteger i = p; i <= max; i *= p) { BigInteger[][] cTable = new BigInteger[p - 1][]; cTable[0] = pre; for (int j = 1; j < p; j++) { BigInteger[] next = ReplaceWith(cTable[0], i * j % PowerTable[p][l], l, p, cMatrix); if (j < p - 1) cTable[j] = MulMod(cTable[j - 1], next, l, p); else pre = MulMod(cTable[j - 1], next, l, p); } PreTable[p].Add(cTable); power++; } } static BigInteger Cmn(BigInteger m, BigInteger n, int l) { InitCMatrix(l); InitPowerTab(l, 5); InitPowerTab(l, 2); BigInteger up5 = CalP(m, n, 5, l); BigInteger up2 = CalP(m, n, 2, l); BigInteger mod = ((up5 - up2) + PowerTable[5][l]) % PowerTable[5][l]; mod = IMod(PowerTable[2][l], mod, PowerTable[5][l]) * PowerTable[2][l] + up2; return mod; } static BigInteger CalP(BigInteger m, BigInteger n, int p, int l) { BigInteger count = Count(m, p) - Count(n, p) - Count(m - n, p); if (count > l) return 0; InitData(l, m, p); BigInteger up = Cal(m, p, l) * PowerTable[p][(int)count]; BigInteger down = Cal(n, p, l); down *= Cal(m - n, p, l); down %= PowerTable[p][l]; up = IMod(down, up, PowerTable[p][l]); return up; } static BigInteger Count(BigInteger v, BigInteger mod) { BigInteger count = 0; while (v > 0) { v /= mod; count += v; } return count; } static List<BigInteger> Values = new List<BigInteger>(); static List<int> Mods = new List<int>(); static BigInteger Cal(BigInteger nums, int p, int l) { BigInteger numsBak = nums; Values.Clear(); Mods.Clear(); while (numsBak > 0) { Values.Add(numsBak); Mods.Add((int)(numsBak % p)); numsBak /= p; } BigInteger result = 1; for (int i = 0; i < Values.Count; i++) { result *= CalSingle(i, p, l); result %= PowerTable[p][l]; } return result; } static BigInteger CalSingle(int cIndex, int p, int l) { int len = Mods[cIndex]; BigInteger sum = 0, last = (Values[cIndex] - len) % PowerTable[p][l]; BigInteger[] pre = new BigInteger[] { 1 }; BigInteger result = 1; cIndex++; for (int i = Mods.Count - 1; i >= cIndex; i--) { int index = Mods[i]; if (index > 0) { BigInteger modValue = 1, current = 0; foreach (var item in PreTable[p][i - cIndex][index - 1]) { if (item != 0) current = (current + modValue * item) % PowerTable[p][l]; if (sum == 0 || modValue == 0) break; modValue = modValue * sum % PowerTable[p][l]; } if (i - cIndex + 1 <= l) sum = (sum + index * PowerTable[p][i - cIndex + 1]) % PowerTable[p][l]; result = (result * current) % PowerTable[p][l]; } } for (int i = 1; i <= len; i++) { if (i % p == 0) continue; result *= last + i; result %= PowerTable[p][l]; } return result; } static BigInteger[] MulTo(int l, int p) { BigInteger[] result = new BigInteger[] { 1 }; for (BigInteger i = 1; i < p; i++) { if (i % p == 0) continue; BigInteger[] b = new BigInteger[] { i, 1 }; result = MulMod(result, b, l, p); } return result; } static BigInteger[] MulMod(BigInteger[] a, BigInteger[] b, int l, int p) { int len = Math.Min(l + 1, a.Length + b.Length - 1); BigInteger[] result = new BigInteger[len]; for (int i = 0; i < Math.Min(a.Length, l + 1); i++) { if (a[i] == 0) continue; int upper = Math.Min(b.Length, l - i + 1); for (int j = 0; j < upper; j++) result[i + j] += a[i] * b[j]; } int last = 0; for (int i = 0; i < result.Length; i++) { result[i] %= PowerTable[p][l - i]; if (result[i] > 0) last = i + 1; } if (last < result.Length) Array.Resize(ref result, last); return result; } //2次方算法,考虑大数是3次方 除以大进制的常数 static BigInteger[] ReplaceWith(BigInteger[] source, BigInteger into, int l, int p, BigInteger[,] cMatrix) { int len = source.Length; len = Math.Min(len, l + 1); BigInteger[] result = new BigInteger[len]; BigInteger[] power = new BigInteger[len]; power[0] = 1; for (int i = 1; i < len; i++) power[i] = power[i - 1] * into % PowerTable[p][l]; for (int i = 0; i < len; i++) { if (source[i] == 0) continue; for (int j = 0; j <= i; j++) { if (power[i] == 0) continue; var tmp = power[i - j] * source[i] % PowerTable[p][l - j]; if (tmp == 0) continue; result[j] += tmp * cMatrix[i, j]; } } for (int i = 0; i < result.Length; i++) result[i] %= PowerTable[p][l - i]; return result; } public static BigInteger EuclidExtend(BigInteger X, BigInteger Y, out BigInteger A, out BigInteger B) { if (Y == 0) { A = 1; B = 0; return X; } BigInteger quotient = X / Y; BigInteger gcd = EuclidExtend(Y, X - Y * quotient, out A, out B); BigInteger Temp = A; A = B; B = Temp - quotient * A; return gcd; } public static bool Linear(BigInteger X, BigInteger Y, BigInteger N, out BigInteger xResult, out BigInteger yResult) { BigInteger gcd = EuclidExtend(X, Y, out xResult, out yResult); if (N % gcd != 0) { return false; } xResult = xResult * N / gcd % Y; xResult = xResult >= 0 ? xResult : xResult + Y; yResult = yResult * N / gcd % X; yResult = yResult <= 0 ? yResult : yResult - X; return true; } public static BigInteger IMod(BigInteger A, BigInteger B, BigInteger P) { BigInteger x, y; Linear(A, P, B, out x, out y); return x; } } }