HDU 6093 - Rikka with Number | 2017 Multi-University Training Contest 5
JAVA+大数搞了一遍- -
不是很麻烦- -
/* HDU 6093 - Rikka with Number [ 进制转换,康托展开,大数 ] | 2017 Multi-University Training Contest 5 题意: 求L,R之间的好数的个数,好数要求在某个d(>=2)进制下数位是0到d-1的 分析: d 进制下好数的个数为 d!-(d-1)! ,且满足 d^(d-1) <= K <= d^d 可知 若 N > d^d 则 1-N 包含前 d-1 个进制的所有好数 寻找零界 d 可以二分,将 N 和 d^d 比大小 计算临界的 d 进制的好数,用类似康托展开的过程 即 对于 (x0, x1, x2...xn),转化成 首位小于x0的所有排列+ 首位等于x0第二位小于x1的所有排列+.... */ import java.math.BigInteger; import java.util.Scanner; public class Main { static Scanner cin = new Scanner(System.in); static long MOD = 998244353; static BigInteger a[] = new BigInteger[2000]; static long F[] = new long[2000]; static BigInteger bb; static String s; static int [] b = new int[5005]; static int [] c = new int[5005]; static int lc, lb; static void init() { F[0] = 1; for (int i = 1; i < 2000; i++) F[i] = F[i-1] * i % MOD; for (int i = 1; i < 2000; i++) a[i] = BigInteger.valueOf(i).pow(i); } static int BinaryFind(){ int l = 2, r = 1999, mid = 0; while (l <= r) { mid = (l+r)/2; if (bb.compareTo(a[mid]) >= 0) l = mid+1; else r = mid-1; } return l; } static void change(int m) { lc = 0; while (lb > -0) { int x = 0; for (int i = lb-1; i >= 0; i--) { x = x*10 + b[i]; b[i] = x/m; x %= m; } c[lc++] = x; while (lb > 0 && b[lb-1] == 0) lb--; } } static int[] vis = new int[5005]; static long solve(){ int m = BinaryFind(); change(m); long ans = F[m-1] - F[1]; if (m > lc) return ans; for (int i = 0; i < m; i++) vis[i] = 0; for (int i = 1; i < c[lc-1]; i++) if (vis[i] == 0) ans = (ans + F[lc-1]) % MOD; vis[c[lc-1]] = 1; for (int i = lc-2; i >= 0; i--) { for (int j = 0; j < c[i]; j++) if (vis[j] == 0) ans = (ans + F[i]) % MOD; if (vis[c[i]] == 1) break; vis[c[i]] = 1; if (i == 0) ans = (ans + 1) % MOD; } return ans; } public static void main(String[] args) { init(); int t = cin.nextInt(); while ((t--) != 0) { bb = cin.nextBigInteger(); s = bb.toString(); lb = s.length(); for (int i = 0; i < lb; i++) { b[i] = (int)(s.charAt(lb-1-i) - '0'); } b[0]--; for (int i = 0; i < lb; i++) { if (b[i] < 0) { b[i] += 10; b[i+1]--; } else break; } while (lb > 0 && b[lb-1] == 0) lb--; long ans = solve(); bb = cin.nextBigInteger(); s = bb.toString(); lb = s.length(); for (int i = 0; i < lb; i++) { b[i] = (int)(s.charAt(lb-1-i) - '0'); } ans = (MOD + solve() - ans) % MOD; System.out.println(ans); } } }
我自倾杯,君且随意