ICPC North America Qualifier Contest 2015 计蒜客

A.

位置数字系统的基(或基数)是用来表示该系统中某个数字的符号数目。基数10系统(也称为十进制)使用10个不同的符号:0、1、…9。
例如,我们将数字72345解释为:
7x 104+2×103+3x 102+4x 101+5x100。
这个例子说明以10为基数时,位置P 0(从右边开始)的符号乘以10P得到它的值。更一般地说,在基底B中,我们使用B符号来表示0,…, B -1,第p位的符号乘以BP得到它的值。
计算中常用的其他基数包括基数2(或二进制,使用符号0和1)、基数8(或八进制,使用符号0-7)和基数16(或十六进制,使用符号0-9和a-f)。在大于10的基数中,字母表示更高的值。因此,在十六进制a-f中表示十进制值10-15,在以> 36为基底的情况下,字母z表示十进制值35。

您的工作是确定jiven算术表达式有效的基。如果两个条件为真,我们定义一个表达式为以B为基底的有效表达式。首先,所有使用的操作数在以B为基础的情况下都是可解释的,其值在十进制范围内[1,232 - 11]。第二,这个表达是正确的。任何表达式在0、1或多个基底中都是有效的。在这个问题中,我们只考虑以1-36为基底时,基底1是一元的。
注意,按照上面列出的约定,一元函数将由一个符号组成:0。在这个问题中,一元数使用符号1而不是0(想想“理货标记”)。例如,一元中的111等于小数3,一元中的11111111等于小数7

给一堆公式判断在1-36那些进制下可以成真

每次要判断其中出现的最大的数字 x x x x + 1 x + 1 x+1开始枚举 要注意1进制 需要所有位都是1 没有0出现

#include <iostream>
#include <cstring>
#include <algorithm>
#include <unordered_map>
#include <string>

using namespace std;

const int N = 35;
typedef long long ll;
#define x first
#define y second
typedef pair<int,int> pii;

int n, maxv, minv;
unordered_map<char,int> book;
unordered_map<int,char> g;

void get_max(string &a) //得到出现过的最大最小值
{
    for (auto c : a)
    {
        maxv = max(book[c], maxv);
        minv = min(book[c], minv);
    }
}

int get(string &x,int p) //得到p进制转换成十进制的数字
{
    int k = 1, sum = 0;
    for (int i = x.size() - 1; i >= 0; i -- )
    {
        sum += k * book[x[i]] * 1ll;
        k *= p;
    }
    return sum;
}

bool get_can(char op,string &a,string &b,string &c,int j)
{
    int A = get(a, j), B = get(b, j), C = get(c, j);
    
    if (B == 0 && op == '/') return false;
    if (op == '+') return (A + B == C);
    else if (op == '-') return (A - B == C);
    else if (op == '*') return (A * B == C);
    else if (op == '/') return (A / B == C && A % B == 0);
}

int main()
{
    for (int i = 0; i < 26; i ++ ) 
    	book['a' + i] = i + 10, g[i + 10] = 'a' + i;
    for (int i = 1; i <= 9; i ++ ) 
    	book['0' + i] = i, g[i] = '0' + i;
    g[36] = '0', book['0'] = 0;
    
    cin >> n;
    
    for (int i = 1; i <= n; i ++ )
    {
        maxv = -1, minv = 50;
        string a, b, c;
        char op, oth;
        cin >> a >> op >> b >> oth >> c;
        get_max(a), get_max(b), get_max(c);
        bool judge = false;
        if (maxv == 1 && minv != 0 && get_can(op, a, b, c, 1)) {judge = true;cout << 1;}
        for (int j = maxv + 1; j <= 36; j ++ )
        {
            if (get_can(op, a, b, c, j)) {judge = true;cout << g[j];}
        }
        if (!judge) puts("invalid");
        else puts("");
    }
    return 0;
}

B.

博比和贝蒂打了个赌。Betty和Bobby打赌,他不可能掷出一个S面骰子(值为1到S),并在Y的至少X上获得一个> R值。贝蒂有各种各样的骰子,每一面都有不同的数字,而且她所有的骰子都是公平的(对于给定的骰子,每一面的结果都是均等的)。为了观察统计上罕见的事件,同时仍然给鲍比一个理由打赌,贝蒂提出支付鲍比WV倍他的赌注在每个遭遇。
例如,假设贝蒂与博比1比特币打赌,他不能在六面骰子上至少三次掷出两次5;如果博比这么做了,她会给他W =3倍于他最初的赌注(即。她会给他3个比特币)。博比应该下这个赌注吗(他的预期回报比他最初的赌注大吗)?

公式: ∑ t = x y C y t ∗ s − r + 1 s t ∗ r − 1 s y − t ∗ w \sum_{t = x}^y{}C_y^t * \frac{s - r + 1}{s} ^ t * \frac{r - 1}{s}^{y - t} * w t=xyCytssr+1tsr1ytw

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 15, M = N * N;
typedef long long ll;
#define x first
#define y second
typedef pair<int,int> pii;

int n;
int c[N][N];

void init()
{
    for (int i = 0; i < N; i ++ )
        for (int j = 0; j <= i; j ++ )
        {
            if (!j) c[i][j] = 1;
            else c[i][j] = c[i - 1][j] + c[i - 1][j - 1];
        }
}

int main()
{
    init();
    cin >> n;
    
    for (int i = 1; i <= n; i ++ )
    {
        double res = 0;
        int r, s, x, y, w;
        cin >> r >> s >> x >> y >> w;
        double a = (double) (s - r + 1) / s, b = 1 - a, a0, b0;
        
        for (int k = x; k <= y; k ++ )
        {
            a0 = 1, b0 = 1;
            for (int j = 1; j <= k; j ++ ) a0 *= a; 
            for (int j = k; j < y; j ++ ) b0 *= b;
            res += (double)c[y][k] * a0 * b0 * w;
        }
        if (res > 1) puts("yes");
        else puts("no");
    }
    return 0;
}

F.

判断没有出现过的单词

#include <iostream>
#include <cstring>
#include <algorithm>
#include <string>

using namespace std;

const int N = 50, M = N * N;
typedef long long ll;
#define x first
#define y second
typedef pair<int,int> pii;

int n;
string x;
int p[N];

int get(char c)
{
    if (c >= 'a' && c <= 'z') return c - 'a';
    else if (c >= 'A' && c <= 'Z') return c - 'A';
    else return 30;
}

int find(int x)
{
    if (p[x] != x) p[x] = find(p[x]);
    return p[x];
}

int main()
{
    cin >> n;
    getline(cin, x);
    for (int k = 1; k <= n; k ++ )
    {
        getline(cin, x);
        for (int i = 0; i <= 26; i ++ ) p[i] = i;
        for (auto c : x)
        {
            int sum = get(c);
            p[sum] = sum + 1;
        }
        if (find(0) == 26) cout << "pangram" << endl;
        else
        {
            cout << "missing ";
            int fa = p[0], son = 0;
            while (fa != 26)
            {
                if (son != fa) son = fa, fa = p[son];
                else 
                {
                    printf("%c", son + 'a');
                    son ++;
                    fa = p[son];
                }
            }
            puts("");
        }
    }
    return 0;
}

G.

一群朋友溜出了校园,但现在他们必须从校园大门回到宿舍,而许多在校园巡逻的老师却没有发现他们。幸运的是,他们有一件隐形衣,但它一次只能遮住两个人。他们将轮流以个人或两人的身份披着斗篷穿过校园(如果其他人还留在学校,他们必须把斗篷还给校门)。每个学生都有他或她能够旅行的最大速度,但是如果一对学生一起在斗篷下走,他们将不得不以两人中较慢的速度旅行。他们的目标是让所有人尽快回到宿舍。
例如,假设组中有四个人,其中一个人 一种一个能够成行的1个1分钟,人乙乙能够在旅行22分钟,人CÇ能够在旅行7和人7分钟dd能在旅行101 0分钟。有可能让每个人都进入宿舍171 7分钟,有以下计划:
– A和B一起从大门到宿舍 (耗时2分钟)
– A带着斗篷返回大门 (耗时1分钟)
– C和D一起从大门到宿舍 (耗时10分钟)
– B带着斗篷返回大门 (耗时2分钟)
–A和B从栅极去宿舍一起 (耗时2分钟)

先把数组排序 从慢到快两两分组 通过最快和第二快的人传斗篷
每次最慢的两个人可以有两种方式
分别和最快的人回宿舍
或者
最快把第二快的人送回去 最慢的两个人一起回去第二快的人带回来斗篷
答案取min就可
最后剩下两个或三个人特判
#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 20, M = N * N;
typedef long long ll;
#define x first
#define y second
typedef pair<int,int> pii;

int n;
int a[N];

int main()
{
    cin >> n;
    for (int i = 1; i <= n; i ++ ) cin >> a[i];
    sort(a + 1, a + 1 + n);
    int res = 0;
    while (n > 3)
    {
        res += min(a[1] + a[2] + a[n] + a[2], a[n] + a[n - 1] + a[1] + a[1]);
        n -= 2;
    }
    
    if (n == 3) res += a[1] + a[2] + a[3];
    else res += a[2];
    
    cout << res << endl;
    
    return 0;
}

H.

Jack和jll开发了一种特殊的加密方法,这样他们就可以享受对话而不用担心窃听者。这里就是:让L原始消息的长度,和M是最小平方数大于或等于L .(马丁)星号添加到消息给填充消息长度M .使用填充消息来填补一个表的大小K x K, K2 = M。以行为主的顺序填充表(从上到下一行,每行从左到右一列)。顺时针旋转桌子90度。加密消息来自于以行为主的顺序从旋转的表中读取消息,省略了任何星号。例如,给定原始消息“iloveyouJack”,则消息长度为L12。因此,paddec消息是’iloveyoulack***,长度M =16。下面是旋转前和旋转后的两个表。
在这里插入图片描述
然后,我们将秘密消息读为“ Jeiaylcookuv”。

每次找到最小的平方数 填充矩阵在旋转输出
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>

using namespace std;

const int N = 2e5 + 10;
typedef long long ll;
#define x first
#define y second
typedef pair<int,int> pii;

int n;
string x;

int main()
{
    cin >> n;
    for (int i = 1; i <= n; i ++ )
    {
        cin >> x;
        int len = x.size();
        int l = sqrt(len);
        if (l * l != len) l ++;
        for (int j = 0; j < l; j ++ )
        {
            for (int k = len / l * l; k >= 0; k -= l)
            {
                if (k + j < len) cout << x[k + j];
            }
        }
        puts("");
    }
    return 0;
}

J.

你已经到了大城市,但你的旅程还没有结束。你仍然必须通过地铁到达你的最终目的地。地铁站的问讯处无人值守,而且是刚从地铁系统的地图上拿出来的。在地板上你注意到地图的碎片。你能拼出足够多的地图来指出怎样到达你的最终目的地吗?
地图上的每个片段恰好包含一个地铁站,同时也标识了它所连接的所有其他地铁站。车站之间的每个连接都是双向的,因此它可以向任何方向移动。使用所有可用的片段,你的任务是确定你必须通过的车站的顺序,以达到你的最终目的地,或者如果你没有足够的信息来完成你的旅程,就没有路线。

把每个字符串标号 dfs或者bfs
#include <iostream>
#include <cstring>
#include <sstream>
#include <algorithm>
#include <unordered_map>
#include <vector>

using namespace std;

const int N = 900, M = N * 2;
typedef long long ll;
#define x first
#define y second
typedef pair<int,int> pii;

int n, cnt = 1, ceng = 1;
string a, b;
unordered_map<string,int> book;
unordered_map<int,string> g;
int h[N], ne[M], e[M], idx;
bool st[N], hav[N][N];
int path[N];

void add(int a,int b)
{
    if (hav[a][b]) return ;
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
    hav[a][b] = true; 
}

void dfs(int u,int fa,int k)
{
    if (k == ceng) return ;
    path[k] = u;
    if (path[ceng - 1] == book[b]) return ;
    
    for (int i = h[u]; ~i; i = ne[i])
    {
        int j = e[i];
        if (j != fa)
            dfs(j, u, k + 1);
        if (path[ceng - 1] == book[b]) return ;
    }
    
}

int main()
{
    cin >> n;
    memset(h, -1, sizeof h);
    for (int i = 1; i <= n; i ++ )
    {
        cin >> a;
        getline(cin,b);
        if (book[a] == 0) g[cnt] = a, book[a] = cnt ++;
        int x = book[a];
        stringstream ssin(b);
        while (ssin >> b)
        {
            if (book[b] == 0) g[cnt] = b, book[b] = cnt ++;
            int y = book[b];
            add(x, y), add(y, x);
        }
    }
    cin >> a >> b;
    if (book[a] == 0) g[cnt] = a, book[a] = cnt ++; // 会输入不存在的字符串
    if (book[b] == 0) g[cnt] = b, book[b] = cnt ++;
    
    while (ceng <= cnt)
    {
        dfs(book[a], -1, 0);
        if (path[ceng - 1] == book[b]) break;
        ceng ++;
    }
    if (path[ceng - 1] == book[b]) 
        for (int i = 0; i < ceng; i ++ ) cout << g[path[i]] << ' ';
    else puts("no route found");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值