43. 投 n 个骰子,计算点数和出现的概率
递归求解:(空间 O(5*n+1),时间 O(6n))
void count(int N, int curN, int sum, int record[]) { if(curN == 0){ ++record[sum - N]; return;} for(int i = 1; i <= 6; ++i) count(N, curN-1, sum+i, record); } void occursNumber(int N, int record[]) { if(N < 1) return; count(N, N, 0, record); }
非递归求解:(空间 O(12*n + 2),时间 O(6*n2))
#include <iostream> #include <cstring> using namespace std; void occursNumber(unsigned N, unsigned record[]) { if(N < 1) return; unsigned *tem = new unsigned[6*N +1]; memset(tem, 0, (6*N+1)*sizeof(unsigned)); bool flag = 1; for(int i = 1; i <= 6; ++i) tem[i] = 1; for(int k = 2; k <= N; ++k) { if(flag) { for(int i = 0; i < k; ++i) record[i] = 0; for(int i = k; i <= 6*k; ++i) { record[i] = 0; for(int j = 1;j <= i && j <= 6; ++j) record[i] += tem[i-j]; } } else { for(int i = 0; i < k; ++i) tem[i] = 0; for(int i = k; i <= 6*k; ++i) { tem[i] = 0; for(int j = 1; j <= i && j <= 6; ++j) tem[i] += record[i-j]; } } flag ^= 1; } if(N & 1) { for(int i = N; i <= 6*N; ++i) record[i] = tem[i]; } delete[] tem; } unsigned long long pow(unsigned exponent) { if(exponent < 1) return 0; unsigned long long result = 6; unsigned long long tem = 1; while(exponent != 1) { if(exponent & 1) tem *= result; result *= result; exponent >>= 1; } result *= tem; return result; } int main(){ unsigned N, S; unsigned long long total; cout << "input the number of dice: N " << endl << "cin >> "; cin >> N; total = pow(N); cout << "the total of all number occurs is : " << total << endl; cout << "=============================" << endl; cout << "input the Sum [N, 6N]" << endl; unsigned *record = new unsigned[6*N + 1]; memset(record, 0, (6*N+1)*sizeof(unsigned)); occursNumber(N, record); while(true) { cout << "cin >> "; cin >> S; if(S >= N && S <= 6*N) cout << record[S] << endl; if(getchar() == 'q') break; } delete[] record; return 0; }
44. 取 k 张扑克牌,看其是否是顺子。
大小王用 0 表示,可以看成任意数字。
bool isContinuous(int data[], int length) { if(data == NULL || length < 1) return false; qsort(data, length, sizeof(int), cmp); int i; int num0 = 0, numGap = 0; for(i = 0; data[i] == 0 && i < length; ++i) ++num0; for(; i < length-1; ++i) { if(data[i] == data[i+1]) return false; numGap += data[i+1] - data[i] - 1; } return (numGap <= num0 ? true : false); } int cmp(const void *arg1, const void* arg2) { return *((int*)arg1) > *((int*)arg2); }
45. 圆圈中最后剩下的数字。
GO:约瑟夫问题