SDUT 2021 Spring Individual Contest - A

F H I 都是字符串的大水题,就看谁的手速快,题目描述多,但是看样例就很容易明白。
去年打天梯赛前对stringstream了解了一下,还不错,这场比赛用到了几次,减少了不少的代码量。

A - All about that base

题目链接

题目大意:简单来说就是问一个等式在1-36进制中,哪个进制可以成立,一个都没有的话就输出 ”invalid“。然后10-35进制是用a-z表示,36进制是用0表示。

分析:题目给出的范围描述是所有的数在10进制下都是不超过long long级别的。所以我们就可以直接暴力判断1-36进制,可以先把当前的进制数用10进制表示,再看等式是否成立。注意题目说:在1进制的时候,只能有数字0,并且用数字1代表数字0。这个会wa在第4个样例。
算是个大模拟,过程比较繁琐。多写多用一下函数,可以少一下代码量,也更加清晰。

code:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;

ll ch(char c) //小写字母转换成10进制数字
{
    ll ans;
    if (c >= 'a' && c <= 'z') ans = c - 'a' + 10;
    else ans = c - '0';
    return ans;
}

ll to(string s, ll q)//q进制转化成10进制的数
{
    ll ans = 0;
    ll n = s.size();
    for (ll i = 0; i < n; i++)
    {
        ll x = ch(s[i]);
        ans += x * pow(q, n - i - 1);
    }
    return ans;
}

bool f(string x, string y, string z, ll q, string op)
{
    ll xx = to(x, q);//获得当前进制下的10进制的值
    ll yy = to(y, q);
    ll zz = to(z, q);
    if (op == "+")
        return xx + yy == zz;
    else if (op == "-")
        return xx - yy == zz;
    else if (op == "*")
        return xx * yy == zz;
    else if (op == "/")//除法要用上强制转换
        return (double)xx / (double)yy == (double) zz;
}

ll pan(string s) //找到最小进制的函数
{
    ll res = 0;
    ll n = s.size();
    for (ll i = 0; i < n; i++)
    {
        ll x = ch(s[i]);
        res = max(res, x);
    }
    return res;
}

bool pan1(string s) //在特判1进制的时候,看有没有数字0
{
    ll n = s.size();
    for (ll i = 0; i < n; i++)
    {
        ll x = ch(s[i]);
        if (x == 0) return false;
    }
    return true;
}

void solve()
{
    ll flag = 0;
    string x, y, z, op1, op2;//输入等式。
    cin >> x;
    cin >> op1;
    cin >> y;
    cin >> op2;
    cin >> z;
    ll ma = 0;//判断一下可能正确的最小的进制,当等式中有9时,最小的进制只能是10,9以下的进制不可能出现数字9
    ma = max(ma, pan(x));
    ma = max(ma, pan(y));
    ma = max(ma, pan(z));
    if (ma == 1)//特判一下1进制
    {
        if (pan1(x) && pan1(y) && pan1(z)) ma = 0;
        else ma = 1;
    }
    for (ll i = ma + 1; i <= 36; i++)//暴力判断1-36进制
    {
        if (f(x, y, z, i, op1))
        {
            if (i <= 9) cout << i;
            else if (i == 36) cout << 0;
            else cout << (char)(i + 'a' - 10);
            flag = 1;
        }
    }
    if (flag == 0) cout << "invalid";
    cout << endl;
}

int main()
{
    ll t;
    cin >> t;
    while (t--) solve();
    return 0;
}

B - Bobby’s Bet

题目链接

题目大意:投掷一个S面的骰子,若能够在Y次以内掷出 >= X次面值 >= R,则可以获得W倍的赌注,但你不喜欢冒险,判断期望回报是否大于原赌注,如果大于,这场bet可以进行,反之,不可以。

分析:就是一道概率期望题,说是高中的数学题也不为过,首先在Y场中先选出k场比赛(k>=x),这k场比赛可以投掷出面值 >= R,其他Y-k场不能投掷出。而投掷出面值 >= R的概率是(S - R + 1) / S。

code:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N = 50;
int c[N][N];

void get_c(int n) //先计算出可能用到的组合数,以防超时
{
    for (int i = 1; i <= n; i++)
    {
        c[i][0] = 1;
        for (int j = 1; j <= i; j++)
        {
            c[i][j] = c[i][j - 1] * (i - j + 1) / j;
        }
    }
}

void solve()
{
    int r, s, x, y, w;
    cin >> r >> s >> x >> y >> w;
    double p = (double)(s - r + 1) / s * 1.0;
    double ans = 0;
    for (int i = x; i <= y; i++)
    {
        ans += pow(p, i) * pow(1 - p, y - i) * c[y][i];
    }
    if (w * ans > 1) cout << "yes" << endl;
    else cout << "no" << endl;
}

int main()
{
    get_c(20);
    ll t;
    cin >> t;
    while (t--) solve();
    return 0;
}

J - Torn To Pieces

题目链接

题目大意:有n个站点,给出每个站点的连接情况,询问能否从一个起点走到终点,可以的话打印出从起点到终点的一条路径,否则,打印“no route found”。题目保证只有一种路径。

分析:很容易想出来是一个普通的dfs+打印路径,因为题目给出的站点都是字符串类型,所以我们需要把每个站点进行编号后,再存入。然后就是dfs找的时候可以从终点到起点找,方便打印路径。

code:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N = 50;
int start, endd;
map<string, int>mp;
map<int, string>mm;
map<int, int>q[N];
int flag = 0;
map<int, int>v[N];
void dfs(int st)
{
    for (int i = 0; i < q[st].size(); i++)//遍历与当前站点相连的站点
    {
        int tt = q[st][i];
        if (v[st][tt] == 1) continue;//避免死循环
        v[st][tt] = 1;
        v[tt][st] = 1;
        if (tt == start)//找到起点就输出并且记录已找到
        {
            flag = 1;
            cout << mm[tt];
            return ;
        }
        dfs(tt);//否则就继续dfs
        if (flag == 1)//上方的dfs中找到路径,说明当前站点是必经之路,打印
        {
            cout << " " << mm[tt];
            return ;
        }
    }
}

int main()
{
    int n, cnt = 1;
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        string s, t;
        string sta;
        cin >> sta;
        if (mp[sta] == 0)//对新的站点进行编号
            mp[sta] = cnt, mm[cnt++] = sta;
        int sta1 = mp[sta];
        getline(cin, s);
        stringstream ss(s);
        while (ss >> t)
        {
            if (mp[t] == 0)//对新的站点进行编号
                mp[t] = cnt, mm[cnt++] = t;
            q[sta1][q[sta1].size()] = mp[t];
            q[mp[t]][q[mp[t]].size()] = sta1;
        }
    }
    string Start, Endd;
    cin >> Start >> Endd;
    start = mp[Start];
    endd = mp[Endd];
    dfs(endd);//从终点到起点找
    if (flag == 0) cout << "no route found";
    else cout << " " << mm[endd];//打印终点
    cout << endl;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值