HDU 6093 Rikka with Number (2017 Multi-Univ Training Contest 5)
来源:互联网 发布:墨子出装 知乎 编辑:程序博客网 时间:2024/06/03 15:12
Problem
d (好数
被定义为:K=
求区间
Limit
Idea
d 进制的最大好数值为
d 进制的最小好数值为
故 d-1 进制下的最大好数与 d 进制下的最小好数满足:
即 d 进制的好数区间与 d-1 进制的好数区间不会重叠。
故具体做法为:
STEP 1. 分别处理子问题 [1, L] 和 [1, R] 中有多少满足条件的好数
STEP 2. 二分枚举最大的 d 进制满足 d 的右区间仍
STEP 3. 在二分后,处理 d+1 进制中有多少满足条件的好数,额外添加即可。
STEP 4. 在处理 d+1 进制时,优先将 N 转换为 d+1 进制的数组,dfs 处理最大的 d+1 进制数。利用康托展开计算个数。
Code
import java.io.*;import java.math.BigInteger;import java.util.Scanner;public class HDU_6093 { public static void main(String[] args) throws IOException { SolverHDU_6093 solver = new SolverHDU_6093(); solver.run(); }}class SolverHDU_6093 { private static final int MOD = 998244353; private static final int N = 5000; private int t; private BigInteger L, R; private long[] factorial = new long[N]; private int[] N2d = new int[N]; private boolean[] vis = new boolean[N]; private int[] maxDNum = new int[N]; private int[] bit = new int[N]; int lowbit(int x) { return x & -x; } void add(int x) { for (int i=x;i<N;i+=lowbit(i)) { bit[i]++; } } int get(int x) { int res = 0; for (int i=x;i!=0;i-=lowbit(i)) { res += bit[i]; } return res; } void init() { factorial[0] = 1; for (int i=1;i<N;i++) { factorial[i] = factorial[i-1] * i % MOD; } } boolean dfs(int idx, int d) { if (idx > d) return true; if (vis[ N2d[idx] ] == true) { for (int p=N2d[idx];p>=0;p--) { if (vis[p] == false) { vis[p] = true; maxDNum[idx] = p; break; } else if (p == 0) { return false; } } for (int i=idx+1, p=d-1;i<=d;i++) { while (vis[p]) p--; maxDNum[i] = p; vis[p] = true; } return true; } else { maxDNum[idx] = N2d[idx]; vis[ N2d[idx] ] = true; if (dfs(idx+1, d) == false) { vis[ N2d[idx] ] = false; if (N2d[idx] == 0) return false; for (int p=N2d[idx]-1;p>=0;p--) { if (vis[p] == false) { vis[p] = true; maxDNum[idx] = p; break; } else if (p == 0) { return false; } } for (int i=idx+1, p=d-1;i<=d;i++) { while (vis[p]) p--; maxDNum[i] = p; vis[p] = true; } return true; } else { return true; } } } long calcExt(BigInteger N, int d) { BigInteger NN = N; for (int i=d;i!=0;i--) { N2d[i] = (int) NN.mod(BigInteger.valueOf(d)).longValue(); NN = NN.divide(BigInteger.valueOf(d)); } if (N2d[1] == 0) return 0; for (int i=0;i<=d;i++) vis[i] = false; vis[ N2d[1] ] = true; maxDNum[1] = N2d[1]; if (dfs(2, d) == false) { if (N2d[1] - 1 == 0) return 0; vis[ N2d[1] ] = false; vis[ N2d[1] - 1 ] = true; maxDNum[1] = N2d[1] - 1; int p = d-1; for (int i=2;i<=d;i++) { while (vis[p] == true) p--; maxDNum[i] = p; vis[p] = true; } } long ans = 0, dig; for (int i=1;i<=d;i++) bit[i] = 0; for (int i=d;i!=0;i--) { dig = get(maxDNum[i]); add(maxDNum[i] + 1); if (i == 1) dig--; ans = (ans + dig * factorial[d-i]) % MOD; } return (ans+1) % MOD; } long calc(BigInteger N) { int l = 2, r = 2000, mid, d = 1; BigInteger maxNumInD; while (l <= r) { mid = (l+r) / 2; maxNumInD = BigInteger.ZERO; for (int j=mid-1;j>=0;j--) { maxNumInD = maxNumInD.multiply(BigInteger.valueOf(mid)); maxNumInD = maxNumInD.add(BigInteger.valueOf(j)); } if (maxNumInD.compareTo(N) <= 0) { l = mid + 1; d = mid; } else { r = mid - 1; } } if (d == 1) return 0; long ans = 0; for (int i=2;i<=d;i++) { ans += factorial[i] - factorial[i-1]; ans %= MOD; } ans += calcExt(N, d+1); ans %= MOD; return ans; } void run() throws IOException { init(); Scanner cin = new Scanner(System.in); t = cin.nextInt(); for (int ica=1;ica<=t;ica++) { L = cin.nextBigInteger(); R = cin.nextBigInteger(); long left = calc(L.subtract(BigInteger.ONE)); long right = calc(R); System.out.println((right - left + MOD) % MOD); } }}
阅读全文
0 0
- HDU 6093 Rikka with Number (2017 Multi-Univ Training Contest 5)
- HDU 6085 Rikka with Candies (bitset, 2017 Multi-Univ Training Contest 5)
- HDU 6090 Rikka with Graph (贪心+构造, 2017 Multi-Univ Training Contest 5)
- HDU 6086 Rikka with String (AC 自动机+状压 dp, 2017 Multi-Univ Training Contest 5)
- HDU 6093 Rikka with Number (2017 Multi-University Training Contest
- 2017 Multi-University Training Contest 5 &&HDU 6085 Rikka with Candies 【bitset+思维】
- HDU 6058 Kanade's sum (链表, 2017 Multi-Univ Training Contest 3)
- HDU 6065 RXD, tree and sequence (LCA, 2017 Multi-Univ Training Contest 3)
- HDU 6071 Lazy Running (Dijstra, 2017 Multi-Univ Training Contest 4)
- HDU 6078 Wavel Sequence (dp + 树状数组, 2017 Multi-Univ Training Contest 4)
- HDU 6069 Counting Divisors (2017 Multi-Univ Training Contest 4)
- HDU 6070 Dirt Ratio (二分+线段树, 2017 Multi-Univ Training Contest 4)
- HDU 6073 Matching In Multiplication (拓扑+DFS, 2017 Multi-Univ Training Contest 4)
- HDU 6046 hash (HASH, 2017 Multi-Univ Training Contest 2)
- HDU 6074 Phone Call (LCA+并查集, 2017 Multi-Univ Training Contest 4)
- HDU 6076 Security Check (DP, 2017 Multi-Univ Training Contest 4)
- HDU 6072 Logical Chain (Biset+Kosaraju, 2017 Multi-Univ Training Contest 4)
- HDU 6096 String (字典树, 2017 Multi-Univ Training Contest 6)
- 人工智能入门的学习
- 过滤器Filter
- mysql语句总结
- Tensorflow学习---tf.nn.embedding_lookup
- A
- HDU 6093 Rikka with Number (2017 Multi-Univ Training Contest 5)
- 58号游戏
- Lock和synchronized比较详解
- HDU3068-manacher算法-最长回文串
- 安装opencv
- C++——CString用法大全
- 每一次学习尝试的终点在哪里?
- tabbaritem 图片太大解决方案
- Laravel-日志管理