ACM刷题之路(三)dfs+排列 第K个幸运排列

简介: ACM刷题之路(三)dfs+排列 第K个幸运排列

题目链接https://vjudge.net/problem/51Nod-1635

 

题解:这题是这学期最后一次模拟赛的A题:

题目大意就是说1到n的第m个全排列中,求下标和数值都是幸运数的个数其中数字全是4或者7的数叫做幸运数

刚开始想了好久,其实跟上次那题全排列类似,前面的数不受影响,可以用深搜判断,因为下标就等于数值,不需要一一分类讨论,第ii项开始,会因为第m个全排列而发生变化,所以要用for循环遍历一遍,当下标和数组的值都是幸运数,再让ans++。

总体思路挺简单的,判断是否幸运数的函数也不难写,中间的全排列产生如果看不懂,可以参考我以前写的博客。

把答案分为两部分,第一部分为1到ii-1不会变的数,第二部分为ii到n会变的数,一个深搜,一个遍历。

直接上代码:

1. #include<iostream>  
2. using namespace std;
3. 
4. long long n, m, ans, a[100], f[100], g[100], n1;
5. long long pd(long long t){//a数组用于判断是否为幸运数
6.  long long n1 = 0;
7.  while (t){
8.    n1++;
9.    a[n1] = t % 10;
10.     t /= 10;
11.     if (a[n1] != 4 && a[n1] != 7)return 0;
12.   }
13.   return 1;
14. }
15. void dfs(long long x) {//dfs深搜
16.   if (x > n1)return;
17.   if (x)ans++;
18.   dfs(x * 10 + 4);
19.   dfs(x * 10 + 7);
20. }
21. int main() {
22.   long long i, ii, j, t, k, s, la;
23.   scanf("%lld%lld", &n, &m);//1到n的第k个排列
24.   t = 1;
25.   for (i = 2; i <= n; i++) {  //这里计算n的阶乘
26.     if (t > m)break;     //用于计算第m种排列会影响最后多少个数字
27.     t *= i;
28.     la = i;
29.   }
30.   if (t < m) { //如果n的阶乘比m小,输出-1
31.     printf("-1");
32.     return 0;
33.   }
34.   ii = la;//ii是受影响的最后数字的总排列个数
35.   k = t;//k是受影响的最后数字的总排列阶乘
36.   for (i = 1; i <= ii; i++){
37.     g[i] = 1;
38.   }
39.   for (i = n - ii + 1; i <= n; i++){ //最后ii+1个数遍历一遍
40.     k /= (ii - (i - (n - ii + 1)));//相当于n!除以n
41.     s = 0;
42.     for (j = 1; j <= ii; j++){
43.       if (g[j]){
44.         s++;
45.         if (s * k >= m){
46.           m -= (s - 1) * k;
47.           g[j] = 0;
48.           f[i - (n - ii)] = j + (n - ii);
49.           break;
50.         }
51.       }
52.     }
53.   }//实现第m个全排列
54.   //全排列产生方法不会的看这里https://blog.csdn.net/qq_41464123/article/details/80584899
55.   n1 = n - ii;      //n1代表全排列中前面不变的数的个数
56.   dfs(0);         //0到n1是不会变的 所以直接暴力模拟
57.   for (i = 1; i <= ii; i++)//显然,ii是第m个排列影响到的最后几位的位数,
58.     //会根据m的排列而变化  所以要判断下标和数值
59.     if (pd(f[i]) && pd(n - ii + i))ans++;
60.   printf("%lld\n", ans);//最后输出两部分的和
61. }


相关文章
|
2月前
|
算法 Java C语言
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-682 求先序排列
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-682 求先序排列
34 0
|
2月前
|
Java C语言 C++
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-基础练习 查找整数
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-基础练习 查找整数
35 0
|
2月前
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-dp练习
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-dp练习
26 0
|
2月前
|
算法 Java C语言
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-627 排列
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-ALGO-627 排列
34 0
|
2月前
|
算法 Java C语言
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-基础练习 杨辉三角形(最好的基础题,没有之一)
第十四届蓝桥杯集训——练习解题阶段(无序阶段)-基础练习 杨辉三角形(最好的基础题,没有之一)
24 0
|
12月前
|
Java
ACM刷题之路(九)数论-逆序组 交换座位
ACM刷题之路(九)数论-逆序组 交换座位
|
12月前
|
Go
ACM刷题之路(十五) 分治法 + 找规律 ZOJ4085
ACM刷题之路(十五) 分治法 + 找规律 ZOJ4085
|
前端开发 JavaScript
#yyds干货盘点# 前端歌谣的刷题之路-第三十七题-从大到小排序
#yyds干货盘点# 前端歌谣的刷题之路-第三十七题-从大到小排序
77 0
#yyds干货盘点# 前端歌谣的刷题之路-第三十七题-从大到小排序
|
Java Python
ACM 选手图解 LeetCode 搜索旋转排序数组Ⅱ
ACM 选手图解 LeetCode 搜索旋转排序数组Ⅱ
ACM 选手图解 LeetCode 搜索旋转排序数组Ⅱ
|
Java Python
ACM 选手图解 LeetCode 搜索旋转排序数组
ACM 选手图解 LeetCode 搜索旋转排序数组
ACM 选手图解 LeetCode 搜索旋转排序数组