杭电计算机学院大学生程序设计竞赛(2015’11)

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;
}