36个高矮不一的人(没有任何两人的身高一样),排成6排,每排6人.....
已知36个高矮不一的人(没有任何两人的身高一样),排成6排,每排6人,条件:每排6人中,站在后面的人要比前面的人高,而且第n+1排的人,要比第n排相应位置的人高,就是后排的人要比前排的人高。求有多少种排列的方法?
问题的答案是:1671643033734960 并且有直接求取的公式.
这个问题前不久由zhangjiupeng在本区提出,自己看到后编了一段程序,没想只能求到5的情况,求N=5的时候就已经需要花近10分钟了,N=6的时候从昨晚20点一直运行到现在还没得出结果(当然我的代码只是最简单的搜索方法,而且有可能有错误)
现在希望大家用程序求一下(不是代公式),欢迎大家贴出自己的代码互相交流
[解决办法]
我的程序不用1分钟,只要执行不到500次递归调用就求出结果。
[解决办法]
我是用递推的方法计算的,执行时间 < 1秒。
这是我的计算结果:
N = 1 ,Result = 1
N = 2 ,Result = 2
N = 3 ,Result = 42
N = 4 ,Result = 24024
N = 5 ,Result = 701149020
N = 6 ,Result = 1671643033734960
N = 7 ,Result = 14684134147796461712
最大只能计算到 N = 7, 当 N = 8 时已经超过了 64位整数范围,懒得写搞精度了,就只算到7吧。
贴代码吧。
#include <stdio.h>#include <string.h>#include <iostream>using namespace std;#define MAXN 7typedef unsigned long long uint64_t;uint64_t ScoreTable[10000000]; // Size >= 10 ^ MAXNint n;int Base[MAXN]; // Base[n] = 10 ^ nvoid Add(int Status[], int CurrentIndex, uint64_t CurrentScore){ int NextIndex = 0; for (int i = 0; i < n; ++i) { if ((0 == i || Status[i] < Status[i-1]) && Status[i] < n) { NextIndex = CurrentIndex + Base[i]; ScoreTable[NextIndex] += CurrentScore; } }}void EnumStatus(int iSum, int iPos, int iMax, int Status[], int CurrentIndex){ if (0 == iSum) { Add(Status, CurrentIndex, ScoreTable[CurrentIndex]); return ; } if (iPos >= n || (n - iPos) * iMax < iSum) { return ; } for (int i = iMax < iSum ? iMax : iSum; i >= 0; --i) { Status[iPos] = i; EnumStatus(iSum - i, iPos + 1, i, Status, CurrentIndex + Base[iPos] * i); }}int main(){ scanf("%d", &n); if (n > MAXN) { printf("Error: %d is greater than %d\n", n, MAXN); return -1; } Base[0] = 1; for (int i = 1; i < MAXN; ++i) { Base[i] = Base[i-1] * 10; } ScoreTable[1] = 1; int Status[MAXN]; for (int i = 1; i <= n * n; ++i) { memset(Status, 0, sizeof Status); EnumStatus(i, 0, n, Status, 0); } int Target = 0; for (int i = 0; i < n; ++i) { Target *= 10; Target += n; } cout << ScoreTable[Target] << endl; return 0;}