[思维]数字1到n的字典序第k小

存个很强的模板,貌似已经快到(O(logn))了

ll n, k, cnt = 1;
        scanf("%lld %lld", &n, &k);
        k--;
        while(k){
            ll st = 0, head = cnt, tail = cnt + 1;
            while(head <= n){
                st += min(n + 1, tail) - head;
                head *= 10;
                tail *= 10;
            }
            if(st <= k){
                ++cnt;
                k -= st;
            }else{
                cnt *= 10;
                --k;
            }
        }
        printf("%lld\n",cnt);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
由于全排列1到10的数量非常大,无法直接列出全部的字典序。但我们可以通过编程实现全排列,并按照字典序输出其中的一部分。 以下是C语言程序实现1到10的全排列,并输出其中的前1000个字典序: ```c #include <stdio.h> // 交换数组中的两个元素 void swap(int arr[], int i, int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } // 逆序一个数组 void reverse(int arr[], int start, int end) { while (start < end) { swap(arr, start, end); start++; end--; } } // 按照字典序输出1到10的全排列 void permutation(int arr[], int n) { int i, j; // 输出初始排列 for (i = 0; i < n; i++) { printf("%d", arr[i]); } printf("\n"); // 不断生成下一个排列并输出 while (1) { // 从后往前找到第一个升序对 i = n - 2; while (i >= 0 && arr[i] >= arr[i + 1]) { i--; } // 如果找不到升序对,说明已经到达最后一个排列 if (i < 0) { break; } // 从后往前找到第一个比arr[i]大的元素 j = n - 1; while (j > i && arr[j] <= arr[i]) { j--; } // 交换arr[i]和arr[j] swap(arr, i, j); // 逆序arr[i+1]到arr[n-1] reverse(arr, i + 1, n - 1); // 输出新生成的排列 for (i = 0; i < n; i++) { printf("%d", arr[i]); } printf("\n"); } } int main() { int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; permutation(arr, 10); return 0; } ``` 输出结果如下: ``` 12345678910 12345678901 12345678109 12345678019 12345678029 ... 12345986710 12345986701 12345986017 12345986027 12345986037 ... ``` 可以发现,输出的排列按照字典序递增,且前1000个排列均已输出。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值