新疆大学ACM-ICPC程序设计竞赛五月月赛(同步赛)F-猴子排序的期望(高精度)

链接: https://www.nowcoder.com/acm/contest/116/F
来源:牛客网
猴子排序的期望


时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
 64bit IO Format: %lld

题目描述


我们知道有一种神奇的排序方法叫做猴子排序,就是把待排序的数字写在卡片上,然后让猴子把卡片扔在空中,等落下的时候观察这些卡片是否从左到右已经排序完成(我们认为不会发生卡片落地后叠在一起的情况)如果有序则排序完成,否则让猴子再扔一遍,直到卡片有序,那么问题来了,给你N个卡片,每个卡片上写着一个大写字母,请问猴子第一次扔这些卡片就按字典序排序完成的概率有多大?   
输入描述:
第一行是一个整数N(1<N<100)表示给猴子N张卡片,接下来是一个长度为N的字符串,代表这些卡片上所写的字母。
输出描述:
输出一行,表示猴子排序第一次就成功的概率(用分子为1的分数表示)。

示例1

输入
7
SCIENCE

输出
1/1260

解题思路:用高精度的乘法先把分子,分母求出来,然后再用高精度的除法把分子化为1即可。所以说,这题你只需要一个高精度的板子就可以了: 大数的四则运算

AC代码:
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<queue>
#include<map>
#define bug printf("--------");
using namespace std;
typedef long long LL;
const int INF = 1e9;
const int MAXSIZE = 200;

int n, a[100];
char str[200], fm[200], s2[5], s3[200], fz[200];

void Mul(char *str1, char *str2, char *str3);
void Div(char *str1, char *str2, char *str3);

//str3 = str1*str2;
//str3 = str1/str2;

int main()
{
    while(~scanf("%d", &n)) {
        scanf("%s", str);
        fz[0] = '1';
        fm[0] = '1';
        fm[1] = '\0';
        fz[1] = '\0';
        memset(a, 0, sizeof(a));
        for(int i = 0; i < n; i ++) {
            a[str[i]] ++;
        }
        for(int i = 1; i < 100; i ++) {
            for(int j = a[i]; j >= 1; j --) {
                sprintf(s2, "%d", j);
                memset(s3, '0', sizeof(s3));
                Mul(fz, s2, s3);
                strcpy(fz, s3); //不断更新
            }
        }
        for(int i = 2; i <= n; i ++) {
            sprintf(s2, "%d", i);
            memset(s3, '0', sizeof(s3));
            Mul(fm, s2, s3);
            strcpy(fm, s3); //不断更新
        }
        memset(s3, '0', sizeof(s3));
        Div(fm, fz, s3);
        printf("1/%s\n", s3);
    }
    return 0;
}

void Mul(char *str1, char *str2, char *str3)
{
    int i, j = 0, i1, i2, tmp, carry, jj;
    int len1 = (int)strlen(str1), len2 = (int)strlen(str2);
    char ch;
    jj = carry = 0;
    for (i1 = len1 - 1; i1 >= 0; --i1)
    {
        j = jj;
        for (i2 = len2 - 1; i2 >= 0; --i2, ++j)
        {
            tmp = (str3[j] - '0') + (str1[i1] - '0') * (str2[i2] - '0') + carry;
            if (tmp > 9)
            {
                carry = tmp / 10;
                str3[j] = tmp % 10 + '0';
            }
            else
            {
                str3[j] = tmp + '0';
                carry = 0;
            }
        }
        if (carry)
        {
            str3[j] = carry + '0';
            carry = 0;
            j++;
        }
        jj++;
    }
    j--;
    while (str3[j] == '0' && j > 0)
    {
        j--;
    }
    str3[++j] = '\0';
    for (i = 0, --j; i < j; ++i, --j)
    {
        ch = str3[i];
        str3[i] = str3[j];
        str3[j] = ch;
    }
    return ;
}

void Div(char *str1, char *str2, char *str3)
{
    int i1, i2, i, j, jj = 0, tag, carry, cf, c[MAXSIZE];
    int len1 = (int)strlen(str1), len2 = (int)strlen(str2), lend;
    char d[MAXSIZE];
    memset(c, 0, sizeof(c));
    memcpy(d, str1, len2);
    lend = len2;
    j = 0;
    for (i1 = len2 - 1; i1 < len1; ++i1)
    {
        if (lend < len2)
        {
            d[lend] = str1[i1+1];
            c[j] = 0;
            ++j;
            ++lend;
        }
        else if (lend == len2)
        {
            jj = 1;
            for (i = 0; i < lend; ++i)
            {
                if (d[i] > str2[i])
                {
                    break;
                }
                else if (d[i] < str2[i])
                {
                    jj = 0;
                    break;
                }
            }
            if (jj == 0)
            {
                d[lend] = str1[i1+1];
                c[j] = 0;
                ++j;
                ++lend;
                continue;
            }
        }
        if (jj == 1 || lend > len2)
        {
            cf = jj = 0;
            while (d[jj] <= '0' && jj < lend)
            {
                ++jj;
            }
            if (lend - jj > len2)
            {
                cf = 1;
            }
            else if (lend - jj < len2)
            {
                cf = 0;
            }
            else
            {
                i2 = 0;
                cf = 1;
                for (i = jj; i < lend; ++i)
                {
                    if (d[i] < str2[i2])
                    {
                        cf = 0;
                        break;
                    }
                    else if (d[i] > str2[i2])
                    {
                        break;
                    }
                    ++i2;
                }
            }
            while (cf)
            {
                i2 = len2 - 1;
                cf = 0;
                for (i = lend - 1; i >= lend - len2; --i)
                {
                    d[i] = d[i] - str2[i2] + '0';
                    if (d[i] < '0')
                    {
                        d[i] = d[i] + 10;
                        carry = 1;
                        --d[i - 1];
                    }
                    else
                    {
                        carry = 0;
                    }
                    --i2;
                }
                ++c[j];
                jj = 0;
                while (d[jj] <= '0' && jj < lend)
                {
                    ++jj;
                }
                if (lend - jj > len2)
                {
                    cf = 1;
                }
                else if (lend - jj < len2)
                {
                    cf = 0;
                }
                else
                {
                    i2 = 0;
                    cf = 1;
                    for (i = jj; i < lend; ++i)
                    {
                        if (d[i] < str2[i2])
                        {
                            cf = 0;
                            break;
                        }
                        else if (d[i] > str2[i2])
                        {
                            break;
                        }
                        ++i2;
                    }
                }
            }
            jj = 0;
            while (d[jj] <= '0' && jj < lend)
            {
                ++jj;
            }
            for (i = 0; i < lend - jj; ++i)
            {
                d[i] = d[i + jj];
            }
            d[i] = str1[i1 + 1];
            lend = i + 1;
            j++;
        }
    }
    i = tag = 0;
    while (c[i] == 0)
    {
        ++i;
    }
    for (; i < j; ++i, ++tag)
    {
        str3[tag] = c[i]+'0';
    }
    str3[tag] = '\0';
    return ;
}

猜你喜欢

转载自blog.csdn.net/i_believe_cwj/article/details/80158683
今日推荐