ICPC Arab Collegiate Programming Contest 2014

45 篇文章 0 订阅
27 篇文章 0 订阅

Problem A. Game of Peace

Program: numbers.(cpp|java)
Input: numbers.in
Balloon Color: Pink
Bob has learned a new magic trick that needs a very special preparation. Once he masters the trick he
will be able to bring peace to the world, but if he fails, the world will be destroyed.
The preparation is performed as follows: There are two containers, initially one is empty and the other
one has X marbles. Bob has a Marble Cloning Machine, it clones the marbles in the container with the
larger number of marbles, then pours the new clones into the other container (e.g. if the two containers
have 7 and 4 marbles, after the cloning step they will have 7 and 11 marbles). The machine does this
cloning operation exactly M times. However, there is a bug in the machine, after it performs N cloning
operations (N M), it will add Y extra marbles to the container with the larger number of marbles.
Then the machine will continue normally with the cloning operation exactly M 􀀀 N times.
During the cloning operations, if both containers have the same number of marbles, any of them can be
considered the one with the larger number of marbles.
Now, the bug in Bob’s machine is threatening to destroy the world. But his nerdy friend Alice told him
that she knows how to fix it. All he has to do is to calculate the greatest common divisor of the sizes of
the two containers after the cloning machine is done. Can you help Bob save the world?
Input
Your program will be tested on one or more test cases. The first line of the input will be a single integer
T (1 T 1,000) representing the number of test cases. Followed by T test cases. Each test case will
consist of a single line, containing 4 integers separated by a single space X, N, Y and M (1 X, Y
1,000) (0 N 70) (N M 100,000) which are the numbers as described above.
Output
For each test case print a single line containing “Case n:” (without quotes) where n is the test case number
(starting from 1) followed by a space then the greatest common divisor of the sizes of the two containers
after the machine is done.
Examples
numbers.in stdout
2
4 3 6 5
5 1 15 2
Case 1: 2
Case 2: 5
Note
In the first sample test case, the number of marbles in each container will be the following after each step:
(4, 0), (4, 4), (4, 8), (12, 8), (18, 8), (18, 26), (44, 26). The greatest common divisor of 44 and 26 is 2.

题目分析:
通过分析前n段数据发现,加来加去他们的gcd并没有改变,所以后面的道理也一样,后面的m-n次加来加去并没有用,计算前n次,然后加个y 直接求gcd就好了,比赛的时候我们还在致力于求到m次

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;
#define LL long long
LL f[100005];
LL gcd(LL a,LL b){
    if(b == 0) return a;
    else return gcd(b,a % b);
}

int main(int argc,char* argv[]) {
    int T,n,m,x,y,kase = 0;
    scanf("%d",&T);
    while(T--) {
        scanf("%d %d %d %d",&x,&n,&y,&m);
        f[0] = 0; f[1] = x;
        for(int i=2; i<=n+1; i++) f[i] = f[i -1] + f[i- 2];
        f[n + 1] += y;
        //for(int i=n+2; i<=m+1; i++) f[i] = f[i - 1] + f[i - 2];
        //for(int i=1; i<=m+1; i++) printf("%lld ",f[i]);
        //printf("\n");
        printf("Case %d: %lld\n",++kase,gcd(f[n],f[n + 1]));
    }


    return 0;
}

Problem B. Let’s Play Tawla

Program: tawla.(cpp|java)
Input: tawla.in
Balloon Color: Blue
Tawla is the Arabic name of the game Backgammon. In Tawla, 2 players alternate playing two 6-face dice.
Each die (singular of dice) face represents a number from 1 to 6 through black dots carved on that face.
Tawla professionals give the numbers 1 to 6 special naming, believed to be adapted from another language.
This special naming is as follows:
1: “Yakk”
2: “Doh”
3: “Seh”
4: “Ghar”
5: “Bang”
6: “Sheesh”
Tawla professionals have this habit of saying the dice number after they throw the dice, in order to have
some sort of game commentary. The higher number is said first.
Some examples:
A dice throw of 1 and 2 is: “Doh Yakk”
A dice throw of 3 and 5 is: “Bang Seh”
A dice throw of 6 and 4 is: “Sheesh Ghar”
If you know more about Tawla, you would know that a double (2 dice producing the same number) does
not follow this rule. For some unknown reason, it doesn’t rhyme to say: “Yakk Yakk” or “Doh Doh”. The
following are their special names:
A 1-1 dice pair is said: “Habb Yakk”
A 2-2 dice pair is said: “Dobara”
A 3-3 dice pair is said: “Dousa”
A 4-4 dice pair is said: “Dorgy”
A 5-5 dice pair is said: “Dabash”
A 6-6 dice pair is said: “Dosh”
One exception to all the above rules is the pair: 5-6 (or 6-5), this one is called “Sheesh Beesh” and not
“Sheesh Bang”! As you may have expected, this is for some unknown reason too.
Write a program that translates dice numbers to Tawla words.
Input
Your program will be tested on one or more test cases. The first line of the input will be a single integer T
(1 T 100) representing the number of test cases. Followed by T test cases. Each test case will consist
of a single line, containing 2 integers separated by a single space a and b (1 a, b 6) representing the
number of black dots carved on the top face of each die.
Output
For each test case print a single line containing “Case n:” (without quotes) where n is the test case number
(starting from 1) followed by a space then the Tawla words describing the given dice numbers.
Examples
tawla.in stdout
3
1 2
2 3
3 4
Case 1: Doh Yakk
Case 2: Seh Doh
Case 3: Ghar Seh
Page 3

题目分析(官方写的、不是我)
后来我也懒,也没再写
先判断输入的 a a a b b b是否相等,如果相等,则根据他们的值输出每对数字对应的字母,如果不相等,先判断是否为特殊情况 5 5 5 6 6 6 6 6 6 5 5 5,是则输出对应字母,否则根据大小先后顺序输出相应的字母
时间复杂度: O ( 1 ) O(1) O(1)

#include <bits/stdc++.h>
using namespace std;

bool cmp(int a, int b) {
    return a > b;
}

int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    int T; cin >> T;
    for (int t = 1; t <= T; t++) {
        int d[2] = { 0 }; cin >> d[0] >> d[1];
        sort(d, d + 2, cmp);
        if (d[0] == 1 && d[1] == 1) {
            printf("Case %d: Habb Yakk\n", t);
        }
        else if (d[0] == 2 && d[1] == 2) {
            printf("Case %d: Dobara\n", t);
        }
        else if (d[0] == 3 && d[1] == 3) {
            printf("Case %d: Dousa\n", t);
        }
        else if (d[0] == 4 && d[1] == 4) {
            printf("Case %d: Dorgy\n", t);
        }
        else if (d[0] == 5 && d[1] == 5) {
            printf("Case %d: Dabash\n", t);
        }
        else if (d[0] == 6 && d[1] == 6) {
            printf("Case %d: Dosh\n", t);
        }
        else if ((d[0] == 5 && d[1] == 6) || (d[0] == 6 && d[1] == 5)) {
            printf("Case %d: Sheesh Beesh\n", t);
        }
        else {
            printf("Case %d: ", t);
            for (int j = 0; j < 2; j++) {
                if (d[j] == 1) {
                    printf("Yakk");
                }
                else if (d[j] == 2) {
                    printf("Doh");
                }
                else if (d[j] == 3) {
                    printf("Seh");
                }
                else if (d[j] == 4) {
                    printf("Ghar");
                }
                else if (d[j] == 5) {
                    printf("Bang");
                }
                else if (d[j] == 6) {
                    printf("Sheesh");
                }
                if (j == 0) {
                    printf(" ");
                }
                else {
                    printf("\n");
                }
            }
        }
    }
    return 0;
}

Problem I. Equivalent Passwords

Program: password.(cpp|java)
Input: password.in
Balloon Color: Gold
Yesterday you arrived at the hotel, and you kept all your valuable stuff in your room’s safe. Unfortunately,
you forgot the password. But you have a very long list of passwords (each password is at most 5 digits),
and you are sure that your password is one of them.
The safe will consider some passwords equivalent. Two passwords A and B are considered equivalent, if
they are of the same length, and |A[i] - B[i]| is the same for all possible values of i, where X[i] is the i-th
digit of X and |Y| is the absolute value of Y.
You will go through the list of passwords in the given order. For each password, you will do the following:

  1. If the same password or any of its equivalent passwords were typed before, skip this password.
  2. Otherwise, type this password into the safe.
  3. If it’s the correct password (or any of its equivalent passwords), the safe will open and you will stop
    any further processing.
    Now given the list of all passwords, you would like to know, in the worst case scenario, what is the
    maximum number of passwords you will have to type?
    Input
    Your program will be tested on one or more test cases. The first line of the input will be a single integer T
    (1 T 50) representing the number of test cases. Followed by T test cases. Each test case starts with
    a line will containing an integer N (1 N 100,000) representing the number of passwords, followed
    by N lines, each one will contain a non-empty string of at most 5 digits (from ‘0’ to ‘9’), representing a
    password (might contain leading zeros).
    Output
    For each test case print a single line containing “Case n:” (without quotes) where n is the test case number
    (starting from 1) followed by a space then the maximum number of passwords you will have to type.
    Examples
    password.in stdout
    3
    3
    000
    111
    222
    4
    1111
    123
    214
    2222
    3
    43434
    54545
    45454
    Case 1: 1
    Case 2: 2
    Case 3: 2
    Page 11 of 13
    ACM International Collegiate Programming Contest, Arab Collegiate Programming Contest 2014
    Egypt, Sharm El Sheikh, November 16th, 2014
    Note
    In the first test case: all passwords are equivalent to each other. This means that the first password will
    open the safe for sure.
    In the second test case:
    If the first password is the correct one, you will type 1 password.
    If the second password is the correct one, you will type 2 passwords.
    If the third password is the correct one, you will type 2 passwords (because the second password is
    equivalent to the third one).
    If the fourth password is the correct one, you will type 1 password (because the first password is
    equivalent to the fourth one).
    In the third test case:
    If the first password is the correct one, you will type 1 password.
    If the second password is the correct one, you will type 1 password (because the first password is
    equivalent to the second one).
    If the third password is the correct one, you will type 2 passwords. Even though the third password
    is equivalent to the second password, the second password was skipped, and therefore you should
    type the third password.

题目大意:
给N个密码,密码 A 和密码 B 如果长度相同,而且对于每个位置 i ,都有 | A[i] - B[i] |相同,那么则称密码 A 和密码 B 是等价的。

输入密码时会跳过和之前输入过密码相等价的密码。求最多要按顺序输入多少个密码。
解题思路:

其实上只需高效判断当前密码是否有相等价的被输入了即可。换个角度考虑,输入了一个新密码的之后,我们会跳过所有与它等价的密码。所以,我们不妨同时也“输入”所有与它等价的密码,然后在之后即容易判断当前密码是否有与它等价的密码被输入过了。
如何枚举所有与它等价的密码?
1、首先是长度相同的。
2、| A i A_i Ai - B i B_i Bi | 每一位都相同。设这个差值为D

可以发现d的取值是 [ 0 , 9 ] [0,9] [0,9],绝对值打开,那么每一位要么是加要么是减。密码最多长5位,所以可能性最多有 2 5 2^5 25种可能。递归枚举 为每一个可能出现的等价

// 又丑又菜的辣鸡代码  一直跑五千一十多毫秒  三个人围着这个改了好多遍
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <string>
#define  Maxn 100005
using namespace std;
char s[Maxn][6],ss[6];
int n,tot,len[Maxn];

inline int judge() {
    int lenth = strlen(ss);
    for(int i=1; i<=tot; i++) {
        if(len[i] != lenth) continue;
        int flag = abs((int)(ss[0] - s[i][0]));
        for(int j=1; j<lenth; j++) {
            if (abs((int) (ss[j] - s[i][j])) != flag) break;
            if(j == lenth - 1) return 0;//  return 0 浠h〃skip鎺?
        }
    }
    return 1;
}

int main(int argc,char* argv[]) {
    ios::sync_with_stdio(false);
    int T,kase = 0; scanf("%d",&T);
    while(T--) {
        scanf("%d",&n);
        int Ans = 1; tot = 1;
        scanf("%s",s[1]);
        len[1] = strlen(s[1]);
        for(int i=2; i<=n; i++) {
            scanf("%s",ss);
            if(judge()) {
                Ans++; ++tot;
                //s[tot] = ss;
                len[tot] = strlen(ss);
                strcpy(s[tot],ss);
            }
        }
        printf("Case %d: %d\n",++kase,Ans);

    }
}
// AC 代码
// 本题看了题解  没有什么高端、骚气的算法  本质思路还是模拟
// 关键在于能否高效的判断等价
#include <iostream>
#include <windows.h>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
using namespace std;
const int Maxn = 1e5 + 9;
bool exist[5][Maxn] = {};
char s[6];
int len;

void DFS(int num,int p,int val) {
    if(p == len) {
        if(s[p] + val <= 9) exist[len][num * 10 + s[p] + val] = 1;
        if(s[p] - val >= 0) exist[len][num * 10 + s[p] - val] = 1;
        return ;
    }
    if(s[p] + val <= 9) DFS(num * 10 + s[p] + val,p + 1,val);
    if(s[p] - val >= 0) DFS(num * 10 + s[p] - val,p + 1,val);
}

int main(int argc,char* argv[]) {
    freopen("password.in","r",stdin);
    freopen("word.out","w",stdout);
    int n,T,kase = 0; scanf("%d",&T);
    while(T--) {
        int Ans = 0;
        scanf("%d",&n);
        memset(exist,0,sizeof(exist));
        for(int i=1; i<=n; i++) {
            scanf("%s",s);
            len = strlen(s) - 1;
            int x = atoi(s);
            if(exist[len][x]) continue;
            Ans ++;
            for(int i=0; i<=len; i++) s[i] -= '0';
            exist[len][x] = 1;
            for(int i=1; i<=9; i++)// 枚举每一位  那个  相同的差值
                DFS(0,0,i);
        }
        printf("Case %d: %d\n",++kase,Ans);
    }
    if(system("fc word.out password.out")) printf("error\n");

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七情六欲·

学生党不容易~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值