Permutation

本题是今天哈理工的一个网络赛上的排列组合题。n个人排成一队,队头的人编号为1,后面的人编号分别为2,3,…,n. 1号人前面没有人,i号人的前面是i-1。 现在Kim想让这n个人重新排队,要求重新排队后编号为i的人前面不能是i-1。问有多少种排队的方法。方案数可能很大,输出答案模1e9+7。

当时做这道题的时候有点乱,光想着打表找规律了,再者是才复出一个月,思维远不如以前,结果就是用了好多时间到最后还是没做出来。网络赛结束后静下心来想了一会儿还是想出来了。如果这道题让高三时的我做,应该很快能AC。

说说思路:用f(n)表示有n个人时的排列方法,现在考虑n+1的情况,当把1排在最后一位时,前面的数字相对于1的位置是任意的,也就是说前面的2~n+1有f(n)种排列方法;当末尾的数字是2~n时,前面的排列方法也是f(n)种,具体为什么我也不知道该怎么表达,拿2在末尾来举例,因为前n个数里没有了1,2组合,1和3是可以互换位置的,这样下来排列方式就会多,但是注意,这个时候以1结尾的数列是不能接在2前面的,于是又要少几种排列,刚好抵消了;当末尾数字是n+1时,前面的排列方法有f(n)-(f(n-1)-(f(n-2)-…)),还是拿具体数字举例,当n=5时,5在末尾时,前面的排列方法应该是f(4)-(4在末尾时的排列方法),而(4在末尾时的排列方法)又等于f(3)-(3在末尾时的排列方法)……递推下去。

递推公式为:f(1)=0,f(2)=1,f(3)=f(2)+f(2)+f(2)-0,f(4)=f(3)+f(3)+f(3)+f(3)-(f(2)-0),f(5)=f(4)+f(4)+f(4)+f(4)+(f(4)-(f(3)-(f(2)-0)))……

因为比赛已经结束,所以不能评测了,贴一个没有MOD的代码,应该是对的吧。。。。。。


   
   
  1. #include<cstdio>
  2. #include<cstring>
  3. #include<cmath>
  4. #include<algorithm>
  5. using namespace std;
  6. const int MOD = 1000000007;
  7. const int maxn = 1000000+ 10000;
  8. int T;
  9. int f[maxn];
  10. void init()
  11. {
  12. freopen( “in.txt”, “r”, stdin);
  13. freopen( “out.txt”, “w”, stdout);
  14. }
  15. void readdata()
  16. {
  17. scanf( “%d”, &T);
  18. }
  19. void work()
  20. {
  21. f[ 1] = 1; f[ 2] = 1;
  22. int cnt = 0;
  23. for( int i = 3; i <= 1000000; i++)
  24. {
  25. f[i] = f[i -1]*i - cnt;
  26. cnt = f[i -1]-cnt;
  27. }
  28. while(T–)
  29. {
  30. int n;
  31. scanf( “%d”, &n);
  32. printf( “%d\n”,f[n]);
  33. }
  34. }
  35. int main()
  36. {
  37. init();
  38. readdata();
  39. work();
  40. return 0;
  41. }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值