2017 多校5 Rikka with Number(数学 + 数位dp)

题意:

统计\([L,R]\)内 有多少数字 满足在某个\(d(d>=2)\)进制下是\(d\)的全排列的

\(1 <= L <= R <= 10^{5000}\)

题解:

首先转化成计算小于等于 \(N\)的好数有多少个。因为 \(n^n<(n+1)^n\)



​​而对于 \(n\) 进制下的任何一个好数 \(K\),都有 \(n^{n-1}<K<n^n
​\)

​​

​​ ,所以每一个进制下好数的大小区间是不相交的。

不难发现 \(d\) 进制下好数的个数为 \(d!-(d-1)!\)

因此我们只需要计算在临界的 \(d\) 进制下,好数的个数就可以了。关于临界的 \(d\),可以用对数估计位数得到。

求 \(d\) 进制下小于等于 \(N\) 的好数个数,先讲 \(N\) 转化成 \(d\) 进制,然后做一个类似康托展开的过程就可以了,因为数据范围很小,所以每一步操作都可以暴力进行。

时间复杂度 \(O(|R|^2)\)。

计算临界状态就用类似数位dp的做法,枚举数字,当不在上界的时候,后面的数字是可以取一个排列,直接算就好了

这样计数是线性的

ps: 做完这题还收获了一份大数模板

  1. #include<bits/stdc++.h>
  2. #define LL long long
  3. #define P pair<int,int>
  4. #define ls(i) seg[i].lc
  5. #define rs(i) seg[i].rc
  6. #define lson l,m,rt<<1
  7. #define rson m+1,r,rt<<1|1
  8. #define ls rt<<1
  9. #define rs (rt<<1|1)
  10. using namespace std;
  11. const int mod = 998244353;
  12. const int MX = 5000;
  13. const int MAXN = 9999;
  14. const int DLEN = 4;
  15. class Big {
  16. public:
  17. int a[MX], len;
  18. Big(const int b = 0) {
  19. int c, d = b;
  20. len = 0;
  21. memset(a, 0, sizeof(a));
  22. while (d > MAXN) {
  23. c = d - (d / (MAXN + 1)) * (MAXN + 1);
  24. d = d / (MAXN + 1);
  25. a[len++] = c;
  26. }
  27. a[len++] = d;
  28. }
  29. Big(const char *s) {
  30. int t, k, index, L, i;
  31. memset(a, 0, sizeof(a));
  32. L = strlen(s);
  33. len = L / DLEN;
  34. if (L % DLEN) len++;
  35. index = 0;
  36. for (i = L - 1; i >= 0; i -= DLEN) {
  37. t = 0;
  38. k = i - DLEN + 1;
  39. if (k < 0) k = 0;
  40. for (int j = k; j <= i; j++) t = t * 10 + s[j] - '0';
  41. a[index++] = t;
  42. }
  43. }
  44. bool operator>(const Big &T)const {
  45. int ln;
  46. if (len > T.len) return true;
  47. else if (len == T.len) {
  48. ln = len - 1;
  49. while (a[ln] == T.a[ln] && ln >= 0) ln--;
  50. if (ln >= 0 && a[ln] > T.a[ln]) return true;
  51. else return false;
  52. } else return false;
  53. }
  54. bool operator==(const Big &T)const {
  55. int ln;
  56. if (len == T.len) {
  57. ln = len - 1;
  58. while (a[ln] == T.a[ln] && ln >= 0) ln--;
  59. return ln < 0;
  60. } else return false;
  61. }
  62. Big operator-(const Big &T)const {
  63. int i, j, big;
  64. bool flag;
  65. Big t1, t2;
  66. if (*this > T) {
  67. t1 = *this;
  68. t2 = T;
  69. flag = 0;
  70. } else {
  71. t1 = T; t2 = *this; flag = 1;
  72. }
  73. big = t1.len;
  74. for (i = 0; i < big; i++) {
  75. if (t1.a[i] < t2.a[i]) {
  76. j = i + 1;
  77. while (t1.a[j] == 0) j++;
  78. t1.a[j--]--;
  79. while (j > i) t1.a[j--] += MAXN;
  80. t1.a[i] += MAXN + 1 - t2.a[i];
  81. } else t1.a[i] -= t2.a[i];
  82. }
  83. t1.len = big;
  84. while (t1.a[t1.len - 1] == 0 && t1.len > 1) {
  85. t1.len--;
  86. big--;
  87. }
  88. if (flag) t1.a[big - 1] = 0 - t1.a[big - 1];
  89. return t1;
  90. }
  91. int operator%(const int &b)const {
  92. int i, d = 0;
  93. for (int i = len - 1; i >= 0; i--) d = ((d * (MAXN + 1)) % b + a[i]) % b;
  94. return d;
  95. }
  96. Big operator/(const int &b)const {
  97. Big ret;
  98. int i, down = 0;
  99. for (int i = len - 1; i >= 0; i--) {
  100. ret.a[i] = (a[i] + down * (MAXN + 1)) / b;
  101. down = a[i] + down * (MAXN + 1) - ret.a[i] * b;
  102. }
  103. ret.len = len;
  104. while (ret.a[ret.len - 1] == 0 && ret.len > 1) ret.len--;
  105. return ret;
  106. }
  107. void print() {
  108. printf("%d", a[len - 1]);
  109. for (int i = len - 2; i >= 0; i--) printf("%d", a[i]);
  110. }
  111. int change(int m,int *s){ ///将大数转化成m进制,保存在字符串s 范围从1到len,并返回长度
  112. int B[MX];
  113. int Le=0; memcpy(B,a,sizeof a);
  114. int tmp = len - 1;
  115. while (tmp >= 0){
  116. int x=0;
  117. for (int i = tmp;i >= 0;i--){
  118. int pre=x; x=(x*(MAXN+1)+B[i])%m; B[i]=(pre*(MAXN+1)+B[i])/m;
  119. }
  120. s[++Le]=x; while(tmp >= 0&&B[tmp]==0) tmp--;
  121. }
  122. return Le;
  123. }
  124. };
  125. char sl[5050],sr[5050];
  126. int f[2000];
  127. int digit[MX];
  128. int vis[MX];
  129. int d;
  130. void init(){
  131. f[0] = 1;
  132. for(int i = 1;i < 2000;i++) f[i] = 1LL * i * f[i-1] % mod;
  133. }
  134. void add(int &x,int y){
  135. x += y;
  136. if(x >= mod) x -= mod;
  137. }
  138. int dfs(int pos,int rbound,int leading_zero){
  139. if(pos == 0) return 1;
  140. if(!rbound) return f[pos];
  141. int r = rbound?digit[pos]:d - 1;
  142. int ans = 0,l = 0;
  143. if(leading_zero) l++;
  144. for(int i = l;i <= r;i++){
  145. if(!vis[i]){
  146. vis[i] = 1;
  147. add(ans,dfs(pos - 1, i == r && rbound,0));
  148. vis[i] = 0;
  149. }
  150. }
  151. return ans;
  152. }
  153. int calc(Big x){
  154. if(x == 0) return 0;
  155. int len = x.change(10,digit),ans = 0;
  156. for(d = 2;;d++){ ///先找到最大的d 在十进制下位数<=len 在d前面的可以直接算
  157. if((int)((d+1)*log10(d+1))+1>len) break;
  158. add(ans, 1LL*(d-1)*f[d-1]%mod);
  159. }
  160. while(1){///暴力枚举d,最多2个,把x转化为d进制的位数和d比较,若位数小于d,超过临界跳出
  161. int pos = x.change(d,digit);
  162. if(pos < d) break;
  163. if(pos > d) add(ans, 1LL*(d-1)*f[d-1]%mod);
  164. else {
  165. memset(vis,0,sizeof(vis));
  166. add(ans,dfs(pos,1,1));
  167. }
  168. d++;
  169. }
  170. return ans;
  171. }
  172. int main(){
  173. init();
  174. int T;
  175. scanf("%d",&T);
  176. while(T--){
  177. scanf("%s%s",sl,sr);
  178. Big l = sl, r = sr;
  179. printf("%d\n",(mod+calc(r)-calc(l-1))%mod);
  180. }
  181. return 0;
  182. }

2017 多校5 hdu 6093 Rikka with Number的更多相关文章

  1. HDU 6093 - Rikka with Number | 2017 Multi-University Training Contest 5

    JAVA+大数搞了一遍- - 不是很麻烦- - /* HDU 6093 - Rikka with Number [ 进制转换,康托展开,大数 ] | 2017 Multi-University Tra ...

  2. 判断相同区间(lazy) 多校8 HDU 5828 Rikka with Sequence

    // 判断相同区间(lazy) 多校8 HDU 5828 Rikka with Sequence // 题意:三种操作,1增加值,2开根,3求和 // 思路:这题与HDU 4027 和HDU 5634 ...

  3. 2017 多校3 hdu 6061 RXD and functions

    2017 多校3 hdu 6061 RXD and functions(FFT) 题意: 给一个函数\(f(x)=\sum_{i=0}^{n}c_i \cdot x^{i}\) 求\(g(x) = f ...

  4. 2017 多校2 hdu 6053 TrickGCD

    2017 多校2 hdu 6053 TrickGCD 题目: You are given an array \(A\) , and Zhu wants to know there are how ma ...

  5. 2017 多校5 Rikka with String

    2017 多校5 Rikka with String(ac自动机+dp) 题意: Yuta has \(n\) \(01\) strings \(s_i\), and he wants to know ...

  6. HDU 6091 - Rikka with Match | 2017 Multi-University Training Contest 5

    思路来自 某FXXL 不过复杂度咋算的.. /* HDU 6091 - Rikka with Match [ 树形DP ] | 2017 Multi-University Training Conte ...

  7. HDU 6088 - Rikka with Rock-paper-scissors | 2017 Multi-University Training Contest 5

    思路和任意模数FFT模板都来自 这里 看了一晚上那篇<再探快速傅里叶变换>还是懵得不行,可能水平还没到- - 只能先存个模板了,这题单模数NTT跑了5.9s,没敢写三模数NTT,可能姿势太 ...

  8. HDU 6085 - Rikka with Candies | 2017 Multi-University Training Contest 5

    看了标程的压位,才知道压位也能很容易写- - /* HDU 6085 - Rikka with Candies [ 压位 ] | 2017 Multi-University Training Cont ...

  9. HDU 5831 Rikka with Parenthesis II(六花与括号II)

    31 Rikka with Parenthesis II (六花与括号II) Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536 ...

随机推荐

  1. JavaWeb各大组件生命周期

    JavaWeb各大组件生命周期 servlet生命周期 服务器打开:在第一次请求时实例化与初始化:然后进行服务:最后服务器关闭销毁 Cookie生命周期:存储在客户端 如果不设置过期时间,则表示这个c ...

  2. 用h+c实现天天生鲜首页

    网页效果图:http://www.dycun.cc/ 如下: css代码 main.css: /*因为大部分的字体都是12px,颜色一致, 所以统一设置下*/ body{ font-size: 12p ...

  3. 自定义扩展Compare比较方法

    public static int Compare<T, V>(this T x, T y, Func<T, V> func) { return Comparer<V&g ...

  4. 移动端h5页面meta标签设置

    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable= ...

  5. 初试PHP连接sql server

    最开始想使用 pdo_sqlsrv 拓展,但是一直没成功,本文采用的是 pdo_dblib + freetds. 环境:CentOS 6.8.PHP 5.6.20 freetds wget ftp:/ ...

  6. mount加载虚拟机增强工具步骤

    1.创建一个挂载目录sudo mkdir /mnt/cdrom 2.在C:\Program Files\Oracle\VirtualBox\VBoxGuestAdditions.iso中添加该文件 3 ...

  7. mybatis在where中比较复杂的判断

    <if test="param.applicationStateInNumber != null and param.applicationStateInNumber != ''&qu ...

  8. SSM框架的简单搭建

    转:https://blog.csdn.net/zhshulin/article/details/37956105 Spring+SpringMVC+MyBatis spring       : 4. ...

  9. LayoutInflater.Factory 妙用

    LayoutInflater.Factory 可以调试 布局,你把下面的代码放到 onCreate里面,然后再里面的下面的onCreateView里面加上断点,然后你就可以知道所有的view构造,所有 ...

  10. idea无法新建maven项目

    之前用的都是eclipse,自从4月底入职新公司后,接触到了idea. 然后自己的电脑上也安装了idea,不过一直都没用,直到昨天打算开起来使用一下. 之后就是想新建一个maven项目,发现死活也新建 ...