其他排列组合问题HDU - 1027 Ignatius and the Princess II(全排列)

举报
用户已注销 发表于 2021/11/19 03:13:18 2021/11/19
【摘要】 目录 HDU - 1027 Ignatius and the Princess II(全排列) HDU - 1220 Cube POJ - 1832 连环锁(九连环的推广) HDU - 1027 Ignatius and the Princess II(全排列) 题目: Description Now our hero...

目录

HDU - 1027 Ignatius and the Princess II(全排列)

HDU - 1220 Cube

POJ - 1832 连环锁(九连环的推广)


HDU - 1027 Ignatius and the Princess II(全排列)

题目:


Description

Now our hero finds the door to the BEelzebub feng5166. He opens the door and finds feng5166 is about to kill our pretty Princess. But now the BEelzebub has to beat our hero first. feng5166 says, "I have three question for you, if you can work them out, I will release the Princess, or you will be my dinner, too." Ignatius says confidently, "OK, at last, I will save the Princess." 

"Now I will show you the first problem." feng5166 says, "Given a sequence of number 1 to N, we define that 1,2,3...N-1,N is the smallest sequence among all the sequence which can be composed with number 1 to N(each number can be and should be use only once in this problem). So it's easy to see the second smallest sequence is 1,2,3...N,N-1. Now I will give you two numbers, N and M. You should tell me the Mth smallest sequence which is composed with number 1 to N. It's easy, isn't is? Hahahahaha......" 
Can you help Ignatius to solve this problem? 
Input

The input contains several test cases. Each test case consists of two numbers, N and M(1<=N<=1000, 1<=M<=10000). You may assume that there is always a sequence satisfied the BEelzebub's demand. The input is terminated by the end of file. 
Output

For each test case, you only have to output the sequence satisfied the BEelzebub's demand. When output a sequence, you should print a space between two numbers, but do not output any spaces after the last number. 
Sample Input

6 4
11 8
Sample Output

1 2 3 5 6 4
1 2 3 4 5 6 7 9 8 11 10

解法一:根据阶乘来计算

因为m<=10000<8!,所以当n>8时,前n-8个数一定是1,2,3,4......n-8

代码:


  
  1. #include<iostream>
  2. using namespace std;
  3. int fac[8] = { 1, 1, 2, 6, 24, 120, 720, 5040 };
  4. int l[9];
  5. void g(int n, int m,int dn) //n is from 1 to 8
  6. {
  7. int flag = (m - 1) / fac[n - 1] + 1;
  8. cout << l[flag]+dn;
  9. for (int i = flag; i<8; i++)l[i] = l[i + 1];
  10. if (n>1)
  11. {
  12. cout << " ";
  13. g(n - 1, m - (flag - 1)*fac[n - 1], dn);
  14. }
  15. else cout << endl;
  16. }
  17. void f(int n, int m)
  18. {
  19. if (n > 8)
  20. {
  21. for (int i = 1; i <= n - 8; i++)cout << i << " ";
  22. g(8, m,n-8);
  23. return;
  24. }
  25. g(n, m, 0);
  26. }
  27. int main()
  28. {
  29. int n, m;
  30. while (cin >> n >> m)
  31. {
  32. for (int i = 0; i < 9; i++)l[i] = i;
  33. f(n, m);
  34. }
  35. return 0;
  36. }

解法二:利用STL

STL中的next_permutation函数可以直接将数组调整到下一顺序的状态。

函数的2个参数,用法和sort里面一样。

比如,对于长为n的数组l,sort(l,l+n)是排序整个数组,next_permutation是给出整个数组的下一顺序的状态。

代码:
 


  
  1. #include<iostream>
  2. #include<algorithm>
  3. using namespace std;
  4. int main()
  5. {
  6. int n, m,l[1001];
  7. while (cin >> n >> m)
  8. {
  9. for (int i = 0; i <= n; i++)l[i] = i;
  10. while (--m)next_permutation(l, l + n+1);
  11. for (int i = 1; i <= n; i++)cout << l[i] << ((i < n) ? " " : "\n");
  12. }
  13. return 0;
  14. }

HDU - 1220 Cube

题目:


Description

Cowl is good at solving math problems. One day a friend asked him such a question: You are given a cube whose edge length is N, it is cut by the planes that was paralleled to its side planes into N * N * N unit cubes. Two unit cubes may have no common points or two common points or four common points. Your job is to calculate how many pairs of unit cubes that have no more than two common points. 

Process to the end of file. 
Input

There will be many test cases. Each test case will only give the edge length N of a cube in one line. N is a positive integer(1<=N<=30). 
Output

For each test case, you should output the number of pairs that was described above in one line. 
Sample Input

1
2
3
Sample Output

0
16
297

这个很容易推导,只要用所有的二元组C(n^3,3),去掉不满足条件的3*n*n*(n-1)即可得到答案

代码:


  
  1. #include<iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. int n, a;
  6. while (cin >> n)
  7. {
  8. a = n*n*(n + 1) + n - 6;
  9. cout << n*n*(n - 1)*a / 2 << endl;
  10. }
  11. return 0;
  12. }

POJ - 1832 连环锁(九连环的推广)

题目:

许多人一定很熟悉九连环(如下图),九个环被串在一起,操作规则如下:第一个(右边)环可以任意装卸,如果第k个环没有被卸掉,而第k个环前边(右边)的所有环都被卸掉,则第k+1个环(第k个环左边的环)可以任意装卸(如果存在的话)。 
用0表示此换被卸掉,1表示此环没有被卸掉,则九连环的每个状态可以用一个长度为9的二进制串来表示,如:111111001经过一次操作可以变成111111000,也可以变成111111011,111111111经过一次操作可以变成111111110,也可以变成111111101。 

任务描述: 
你现在要操作的是一个n连环,n为正整数,给出n连环的两种状态,计算出从第一种状态变换到第二种状态所需要的最少步数。 
Input
第一行是一个正整数m,表示有m组测试数据。 
每组测试数据一共3行,第一行是一个正整数n (0 < n < 128),后两行每一行描述一种状态,n个数(0或1),用空格隔开。 
Output
对于每一组测试数据输出一行,一个非负整数,表示从第一种状态变换到第二种状态所需要的最少步数。
Sample Input
2
3
0 0 0
1 0 0
4
1 0 0 0
0 1 1 0
Sample Output
7
11

递推式并不难找,如果把状态看成1个二进制数,比如1000就是8,0110就是6,记为状态8、状态6
假设从状态n转移到转态0需要的最少步数为f(n),那么f(n*2)=f(n)*2+f(n)%2,f(n*2+1)=f(n)*2+1-f(n)%2

这样,只需要从左往右扫描就可以得出该状态的f()值,把2个状态的f()值相减即为2个转态之间转移的最少步数,这一点,可以从f()的定义(最小性)推导出来

代码:
 


  
  1. import java.util.*;
  2. import java.math.BigInteger;
  3. public class Main
  4. {
  5. public static void main(String[] args)
  6. {
  7. Scanner cin = new Scanner(System.in);
  8. int m=Integer.parseInt(cin.next());
  9. while (m-->0)
  10. {
  11. int n=Integer.parseInt(cin.next());
  12. BigInteger a=new BigInteger("0"),b=new BigInteger("0");
  13. for(int i=0;i<n;i++)
  14. if(Integer.parseInt(cin.next())==0)a=a.multiply(BigInteger.valueOf(2)).add(a.mod(BigInteger.valueOf(2)));
  15. else a=a.multiply(BigInteger.valueOf(2)).add(BigInteger.valueOf(1)).subtract(a.mod(BigInteger.valueOf(2)));
  16. for(int i=0;i<n;i++)
  17. if(Integer.parseInt(cin.next())==0)b=b.multiply(BigInteger.valueOf(2)).add(b.mod(BigInteger.valueOf(2)));
  18. else b=b.multiply(BigInteger.valueOf(2)).add(BigInteger.valueOf(1)).subtract(b.mod(BigInteger.valueOf(2)));
  19. System.out.println(a.subtract(b).abs());
  20. }
  21. }
  22. }

 

 

文章来源: blog.csdn.net,作者:csuzhucong,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/nameofcsdn/article/details/115922267

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。