1003 玩骰子
暴力枚举抛的骰子的点数,算出获胜的方案数,然后在三个里面选择最大值。
#include <bits/stdc++.h> using namespace std; int a[4], b[4]; bool all_same(int *c) { return (c[1] == c[2] && c[2] == c[3]); } bool two_same(int *c) { return (c[1] == c[2] || c[2] == c[3]); } bool ok(void) { if (all_same (a)) { if (!all_same (b)) return true; else { if (all_same (b) && a[1] > b[1]) return true; } } else if (two_same (a) && !all_same (a)) { int x1 = a[1], y1= a[3]; if (a[2] == a[3]) swap (x1, y1); if (!all_same (b) && !two_same (b)) return true; else if (two_same (b) && !all_same (b)) { int x2 = b[1], y2 = b[3]; if (b[2] == b[3]) swap (x2, y2); if (x1 > x2) return true; else if (x1 == x2 && y1 > y2) return true; } } else { if (!all_same (b) && !two_same (b)) { if (a[3] > b[3]) return true; else if (a[3] == b[3]) { if (a[2] > b[2]) return true; else if (a[2] == b[2]) { if (a[1] > b[1]) return true; } } } } return false; } int run(int id) { int ret = 0; int c[4]; for (int i=1; i<=3; ++i) c[i] = a[i]; for (int i=1; i<=6; ++i) { for (int j=1; j<=3; ++j) { a[j] = c[j]; } a[id] = i; sort (a+1, a+1+3); if (ok ()) ret++; } for (int i=1; i<=3; ++i) a[i] = c[i]; return ret; } int main(void) { int T; scanf ("%d", &T); while (T--) { for (int i=1; i<=3; ++i) scanf ("%d", &a[i]); for (int i=1; i<=3; ++i) scanf ("%d", &b[i]); sort (a+1, a+1+3); sort (b+1, b+1+3); if (ok ()) { printf ("1.000 "); continue; } double ans = 0; for (int i=1; i<=3; ++i) { int cnt = run (i); ans = max (ans, cnt / 6.0); } printf ("%.3f ", ans); } return 0; }
1005 ACM组队安排
两种做法:1. 递推公式,可以从n-1中选择0, 1, 2个人,然后乘上dp[n-i]的方案
2. 排列组合,
计算公式:f[n]=∑{ com(n,i)*com(n-i,j*2)*equa(j*2,2)/fac[j]*equa(k*3,3)/fac[k] },(i+2*j+3*k=n)
一人一组:com(n,i) 从n个人中选i个人
两人一组:com(n-i,j*2)*equa(j*2,2)/fac[j] 从n-i个人中选出2*j个人,并且将这2*j个人无序地平分成j组
三人一组:equa(k*3,3)/fac[k] ,将剩余的3*k个人无序地平分成k组
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int MOD = 1e9 + 7; int fact[15]; int comb[22][22]; ll dp[21]; ll equa(int n, int m) { ll ret = 1; while (n) { ret *= comb[n][m]; n -= m; } return ret; } void Comb(void) { for (int i=0; i<21; ++i) { comb[i][i] = comb[i][0] = 1; for (int j=1; j<i; ++j) { comb[i][j] = comb[i-1][j] + comb[i-1][j-1]; if (comb[i][j] >= MOD) { comb[i][j] -= MOD; } } } } void init(void) { Comb (); fact[0] = fact[1] = 1; for (int i=2; i<=13; ++i) { fact[i] = fact[i-1] * i; } for (int i=0; i<=20; ++i) { for (int j=0; j<=10; ++j) { for (int k=0; k<=6; ++k) { if (i + 2 * j + 3 * k <= 20) { int m = i + 2 * j + 3 * k; dp[m] += comb[m][i] * comb[m - i][2 * j] * equa (2 * j, 2) / fact[j] * equa (3 * k, 3) / fact[k]; } } } } } void solve(void) { dp[1] = 1; dp[2] = 2; dp[3] = 5; dp[4] = 14; for (int i=5; i<=20; ++i) { dp[i] = dp[i-1] + (i - 1) * dp[i-2] + (i - 1) * (i - 2) / 2 * dp[i-3]; } } int main(void) { //init (); solve (); int n; while (scanf ("%d", &n) == 1) { if (!n) break; printf ("%I64d ", dp[n]); } return 0; }
1006 逆袭指数
暴力枚举sqrt (n)的长度
#include <bits/stdc++.h> using namespace std; const int N = 1e3 + 5; int ans[N], v[N]; int mx; void DFS(int n, int m, int len) { if (n % m == 0) { v[len] = m; DFS (n / m, m + 1, len + 1); } else if (len > mx) { mx = len; for (int i=0; i<len; ++i) ans[i] = v[i]; } } int main(void) { int n; while (scanf ("%d", &n) == 1) { mx = 0; int k = sqrt (n) + 2; for (int i=2; i<=k; ++i) { DFS (n, i, 0); } if (!mx) { printf ("1 %d ", n); continue; } printf ("%d ", mx); printf ("%d", ans[0]); for (int i=1; i<mx; ++i) { printf ("*%d", ans[i]); } puts (""); } return 0; }