SDUTACM集训第一次选拔AC代码(2018)

比赛链接:

https://acm.sdut.edu.cn/onlinejudge2/index.php/Home/Contest/problemlist/cid/2703
下面写一下自己的解题报告和感受:

目录:

A - 双色Hanoi塔问题

B - 进制转换

C - 质数中的质数

D - 王小二切饼

E - 组合数的计算

F - 完美字符串

G - 取数字问题

H - 皮卡丘的伙伴是?


A - 双色Hanoi塔问题

思路:

<1>把n-1个盘子借助b柱子 从a柱子上移到c柱子上    所以move(n-1,a,c,b)  递归实现

<2>把最后一个  也是最大的盘子移到b上  也就是两个move()中间夹着的那一句      //  move(原柱子,目标柱子,借助柱子)

<3>把n-1个盘子借助a柱子 从c柱子上移到b柱子上    所以move(n-1,c,b,a)  递归实现

#include 
using namespace std;
void move(int n, char a, char b, char c);
int main()
{
    int n;
    cin >> n;
    move(n, 'A', 'B', 'C');
    cout << endl;
    return 0;
}
void move(int n, char a, char b, char c)
{
    if (n == 1)
        printf("%d %c %c\n", n, a, b);
    else
    {
        move(n - 1, a, c, b);
        printf("%d %c %c\n", n, a, b);
        move(n - 1, c, b, a);
    }
}


B - 进制转换

特别注意:n=0的时候

#include 
using namespace std;
int main()
{
    long long n;
    int r;
    char s[6] = {'A', 'B', 'C', 'D', 'E', 'F'};
    while (~scanf("%lld %d", &n, &r))
    {
        int cnt = 0, flag = 0;
        char str[100000];
        if (n < 0)
        {
            n = abs(n);
            flag = 1;
        }
        else if (n == 0)
            flag = 2;
        for (int i = 0;; i++)
        {
            if (n == 0)
                break;
            int t = n % r;
            if (t >= 10)
                str[i] = s[t - 10];
            else
                str[i] = t + '0';
            n /= r;
            cnt++;
        }
        if (flag == 2)
            printf("0");
        else if (flag == 1)
        {
            printf("-");
            for (int i = cnt - 1; i >= 0; i--)
                putchar(str[i]);
        }
        else
        {
            for (int i = cnt - 1; i >= 0; i--)
                putchar(str[i]);
        }
        printf("\n");
    }
    return 0;
}

C - 质数中的质数

思路:

埃筛  筛素数  

#include 
using namespace std; //埃筛
int p, prime[10000001];
bool isprime[10000001];
void sieve()
{
    p = 1;
    for (int i = 0; i <= 1e7; i++)
        isprime[i] = true;
    isprime[0] = false, isprime[1] = false;
    for (int i = 2; i <= 1e7; i++)
    {
        if (isprime[i])
        {
            prime[p++] = i;
            for (int j = 2 * i; j <= 1e7; j += i)
                isprime[j] = false;
        }
    }
}
int main()
{
    int n, i;
    sieve();
    while (~scanf("%d", &n))
    {
        for (i = 1; i < p; i++)
        {
            if (prime[i] >= n && isprime[i])
                break;
        }
        printf("%d\n", prime[i]);
    }
    return 0;
}


D - 王小二切饼(递推)

#include 
using namespace std;
int main()
{
    int dp[111];
    int n;
    cin >> n;
    dp[1] = 2;
    for (int i = 2; i <= n; i++)
        dp[i] = dp[i - 1] + i;
    cout << dp[n] << endl;
    return 0;
}


E - 组合数的计算

解法一:

思路:

把分子上能够整除2的数  换成2  分母中约去相应的值   

例如 

分子上有个  40   40%2==0  分子上一定有个20与之对应 

把分母上的40换成2   分子上的20换为1  分别存入对应的数组中

#include 
using namespace std;
int arr[41];
int brr[41];
void c(int a, int b)
{
    for (int i = 0; i < 41; i++)  //注意一定要初始化否则每进行一次高精运算的下一次运算会错
    {
        arr[i] = 0;
        brr[i] = 0;
    }
    for (int i = 1; i <= b; i++)
        arr[i] = i;
    int cnt = 1;
    double m = 1.0, n = 1.0;
    for (int i = a; cnt <= b; i--)
    {
        brr[i] = i;
        cnt++;
        if (brr[i] % 2 == 0 && arr[brr[i] / 2] > 1)
        {
            arr[brr[i] / 2] = 1;
            brr[i] = 2;
        }
        m *= brr[i];
    }
    for (int i = 1; i <= b; i++)
        n *= arr[i];
    printf("%.0lf\n", m / n);
}
int main()
{
    int n, a, b;
    scanf("%d", &n);
    while (n--)
    {
        scanf("%d %d", &a, &b);
        if (a < b)
            printf("0\n");
        else if (a / 2 < b)
            c(a, a - b);
        else
            c(a, b);
    }
    return 0;
}

解法二:

思路:

牢记组合数递推公式   c[i][j] = c[i - 1][j] + c[i - 1][j - 1];

#include  //组合数公式
using namespace std;
long long c[45][45];
int main()
{
    int n, a, b;
    scanf("%d", &n);
    for (int i = 0; i <= 41; i++)
        c[i][0] = 1;

    for (int i = 1; i <= 41; i++)
        for (int j = 1; j <= i; j++)
            c[i][j] = c[i - 1][j] + c[i - 1][j - 1];
    while (n--)
    {
        scanf("%d %d", &a, &b);
        printf("%lld\n", c[a][b]);
    }
    return 0;
}

F - 完美字符串

#include 
using namespace std;
int main()
{
    char str[10001];
    while (gets(str))
    {
        int ans = 26, a[100] = {0};
        for (int i = 0; i < strlen(str); i++)
        {
            if (str[i] >= 'a' && str[i] <= 'z')
                str[i] -= 32;
            a[str[i]]++;
        }
        int sum = 0;
        sort(a + 65, a + 91);
        for (int i = 90; i >= 65; i--)
        {
            if (a[i] == 0)
                continue;
            else
            {
                sum += a[i] * ans;
                ans--;
            }
        }
        printf("%d\n", sum);
    }
    return 0;
}


G - 取数字问题

思路:

暴力搜索:递归实现

在i < m  和  j < n的前提下   搜索对应数的   右侧的数  和下方的数

注意:有多种路线走到右下方  所以有多个sum  所以sum

当  搜索到右下方数字时候  如果sum>0  返回sum  否则 满足条件输出-1

#include 
using namespace std; //暴力搜索
int m, n, a[11][11];
int ans = 501966782;
void search(int i, int j, int sum)
{
    sum += a[i][j];
    if (i < m)
        search(i + 1, j, sum);
    if (j < n)
        search(i, j + 1, sum);
    if (i == m && j == n && sum < ans && sum > 0)
        ans = sum;
}
int main()
{
    scanf("%d%d", &m, &n);
    for (int i = 1; i <= m; i++)
        for (int j = 1; j <= n; j++)
            scanf("%d", &a[i][j]);
    search(1, 1, 0);
    if (ans == 501966782)
        ans = -1;
    printf("%d\n", ans);
    return 0;
}


H - 皮卡丘的伙伴是?  模拟题义即可

注意:

既不克制也不抵抗时的情况

#include 
using namespace std;
int isok(char *s1, char *s2)
{
    if (strcmp("Water", s1) == 0)
    {
        if (strcmp("Fire", s2) == 0)
            return 1;
        if (strcmp("Grass", s2) == 0 || strcmp(s1, s2) == 0)
            return 0;
    }
    else if (strcmp("Fire", s1) == 0)
    {
        if (strcmp("Grass", s2) == 0)
            return 1;
        if (strcmp("Water", s2) == 0 || strcmp(s1, s2) == 0)
            return 0;
    }
    else if (strcmp("Grass", s1) == 0)
    {
        if (strcmp("Water", s2) == 0)
            return 1;
        if (strcmp("Fire", s2) == 0 || strcmp(s1, s2) == 0)
            return 0;
    }
    else if (strcmp("Electric", s1) == 0)
    {
        if (strcmp("Water", s2) == 0)
            return 1;
        if (strcmp("Grass", s2) == 0 || strcmp(s1, s2) == 0)
            return 0;
    }

    return -1;
}
int main()
{
    char s1[10], s2[10], cc[10];
    float a, b, c;
    while (~scanf("%s %s", s1, s2))
    {
        scanf("%f %f %s", &a, &b, cc);
        a *= 1.5;
        if (isok(s1, s2) == 1)
        {
            a *= 2;
            if (strcmp("Normal", cc) == 0 || isok(cc, s2) == -1)
                c = 60.0;
            else if (isok(cc, s2) == 1)
                c = 60 * 2.0;
            else if (isok(cc, s2) == 0)
                c = 60.0 / 2;
        }
        else if (isok(s1, s2) == 0)
        {
            a /= 2;
            if (strcmp("Normal", cc) == 0 || isok(cc, s2) == -1)
                c = 60.0;
            else if (isok(cc, s2) == 1)
                c = 60 * 2.0;
            else if (isok(cc, s2) == 0)
                c = 60.0 / 2;
        }
        else if (isok(s1, s2) == -1)
        {
            if (strcmp("Normal", cc) == 0 || isok(cc, s2) == -1)
                c = 60.0;
            else if (isok(cc, s2) == 1)
                c = 60 * 2.0;
            else if (isok(cc, s2) == 0)
                c = 60.0 / 2;
        }
        float num[4];
        int cnt[4] = {0, 1, 2, 3};
        num[cnt[1]] = a, num[cnt[2]] = b, num[cnt[3]] = c;
        for (int i = 1; i < 3; i++)
        {
            for (int j = i + 1; j <= 3; j++)
            {
                if (num[i] < num[j])
                {
                    float t = num[i];
                    num[i] = num[j];
                    num[j] = t;
                    int o = cnt[i];
                    cnt[i] = cnt[j];
                    cnt[j] = o;
                }
            }
        }
        printf("%d\n", cnt[1]);
    }
    return 0;
}

 

你可能感兴趣的:(SDUTACM集训第一次选拔AC代码(2018))