HDU 6093 Rikka with Number (2017 Multi-Univ Training Contest 5)
2017-08-14 14:56
423 查看
Problem
d (d≥2)进制下的好数被定义为:K=(A1A2...Ad)d , 其中 Ai≠Aj 且 0≤Ai≤d−1 ,同时 A1≠0
求区间 [L,R] 中多少数恰好是 d 进制下的好数 ?
Limit
1≤L≤R≤105000L,R 为十进制数
Idea
d 进制的最大好数值为 (d−1)⋅dd−1+(d−2)⋅dd−2+⋯+0⋅d0d 进制的最小好数值为 1⋅dd−1+0⋅dd−2+2⋅dd−3+⋯+(d−1)⋅d0
故 d-1 进制下的最大好数与 d 进制下的最小好数满足:
(d−2)⋅(d−1)d−2+(d−3)⋅(d−1)d−3+⋯+0⋅(d−1)0<1⋅dd−1+0⋅dd−2+2⋅dd−3+⋯+(d−1)⋅d0
即 d 进制的好数区间与 d-1 进制的好数区间不会重叠。
故具体做法为:
STEP 1. 分别处理子问题 [1, L] 和 [1, R] 中有多少满足条件的好数
STEP 2. 二分枚举最大的 d 进制满足 d 的右区间仍 ≤N (N 作为区间的右值 [1, N]) 。
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 ; private int[] N2d = new int ; private boolean[] vis = new boolean ; private int[] maxDNum = new int ; private int[] bit = new int ; 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); } } }
相关文章推荐
- HDU 6093 Rikka with Number (2017 Multi-University Training Contest - Team 5)
- HDU 6086 Rikka with String (AC 自动机+状压 dp, 2017 Multi-Univ Training Contest 5)
- HDU 6090 Rikka with Graph (贪心+构造, 2017 Multi-Univ Training Contest 5)
- HDU 6085 Rikka with Candies (bitset, 2017 Multi-Univ Training Contest 5)
- 2017 Multi-University Training Contest - Team 5:Rikka with Number
- HDU 6086 Rikka with String(2017 Multi-University Training Contest 3)
- HDU 6088 - Rikka with Rock-paper-scissors | 2017 Multi-University Training Contest 5
- HDU 6076 Security Check (DP, 2017 Multi-Univ Training Contest 4)
- HDU 6138 Fleet of the Eternal Throne (后缀数组+字典树, 2017 Multi-Univ Training Contest 8)
- 2017 Multi-University Training Contest - Team 5 Rikka with Competition
- HDU 6071 Lazy Running (Dijstra, 2017 Multi-Univ Training Contest 4)
- HDU 6124 Euler theorem (2017 Multi-Univ Training Contest 7)
- HDU 6078 Wavel Sequence (dp + 树状数组, 2017 Multi-Univ Training Contest 4)
- 2017 Multi-University Training Contest - Team 5 1008 Rikka with Subset
- HDU 6133 Army Formations (树状数组, 2017 Multi-Univ Training Contest 8)
- HDU 6127 Hard challenge (极角排序+二分, 2017 Multi-Univ Training Contest 7)
- HDU 6069 Counting Divisors (2017 Multi-Univ Training Contest 4)
- 2017 Multi-University Training Contest - Team 5 1006 Rikka with Graph
- 2017 Multi-University Training Contest 5 solutions 1006 Rikka with Graph
- 2017 Multi-University Training Contest - Team 5-Rikka with Subset