轉載自:http://blog.csdn.net/u013611908/article/details/44545955ios
題目大意:一副牌除掉大小王,而後有一些已經造成了序列,讓你算剩下的牌能組合出多少種比給的序列小的組合。測試
思路:搜索,分這個位置相同或者小於,假如放一個小於的,則剩下的就是全排列spa
只不過這邊的全排列是相同元素的全排列。.net
所採起的是位置的選擇的排列方式。blog
好比1112233這個全部的狀況就是c(7,3)*c(4,2)*c(2,2)string
題目wa了不少發。it
題目須要注意,是嚴格小於,等因而不行的。io
另外就是涉及到剩的張數比給的少的狀況。class
這邊直接給數據讓你們測試吧,ps:是抄別人的。stream
Input:
#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<cstring> #include<cstdio> using namespace std; #define mod 1000000007 int a[15]; char str[60]; long long ans = 0; long long c[60][60]; void init() { for (int i = 0; i < 60;i++)c[i][0] = c[i][i] = 1; for (int i = 2; i < 60;i++) for (int j = 1; j < i; j++) c[i][j] = (c[i - 1][j] + c[i - 1][j - 1])%mod; } long long gao(int sum) { long long ans = 1; for (int i = 1; i < 14; i++) { ans = (ans*c[sum][a[i]])%mod; sum -= a[i]; } return ans; } void dfs(int cur, int sum) { if (!str[cur]) { return; } if (sum == 0) { ans++; return; } int k = str[cur] - 48; for (int i = 1; i<k; i++) { if (a[i]>0) { a[i]--; ans = (ans + (gao(sum-1)) % mod) % mod; a[i]++; } } if (a[k]>0) { a[k]--; dfs(cur + 1, sum - 1); } } int main() { init(); while (~scanf("%s", str)) { int len = strlen(str); int j = 0; for (int i = 1; i < 14; i++) a[i] = 4; for (int i = 0; i < len; i++) { if (str[i] == 'A') { str[j++] = 1 + 48; a[1]--; } else if (str[i] == '1') { str[j++] = 10 + 48; a[10]--; } else if (str[i] == 'J') { str[j++] = 11 + 48; a[11]--; } else if (str[i] == 'Q') { str[j++] = 12 + 48; a[12]--; } else if (str[i] == 'K') { str[j++] = 13 + 48; a[13]--; } else if (str[i] == '0') continue; else { str[j++] = str[i]; a[str[i] - 48]--; } } str[j] = 0; int sum = 0; for (int i = 1; i < 14; i++) sum += a[i]; ans = 0; if (sum != 0) dfs(0, sum); printf("%lld\n", ans); } return 0; }