ccnu_2016_summer_week1(1)

集训第一周第一套都是一些基础题,主要是熟悉编程,以及简单的解题思维


A:Least Common Multiple
http://acm.hdu.edu.cn/showproblem.php?pid=1019【hdu1019】

Problem Description
The least common multiple (LCM) of a set of positive integers is the smallest positive integer which is divisible by all the numbers in the set. For example, the LCM of 5, 7 and 15 is
105.

Input Input will consist of multiple problem instances. The first line of the input will contain a single integer indicating the number of problem instances. Each instance will consist of a single line of the form m n1 n2 n3 … nm where m is the number of integers in the set and n1 … nm are the integers. All integers will be positive and lie within the range of a 32-bit integer.

Output For each problem instance, output a single line containing the corresponding LCM. All results will lie in the range of a 32-bit integer.

Sample Input

2 3 5 7 15 6 4 10296 936 1287 792 1

Sample Output

105 10296

【题面大意】:给出n个数求这n个数的最小公倍数。
【解法】:由lcm(a, b) = a * b / gcd(a, b)可以计算得出两个数的最小公倍数,若是多个数,只需要从前往后每次取两个数a, b计算lcm(a, b),再将计算结果lam(a, b)作为新的数参加运算即可。
计算k个数的最小公倍数
【gcd参考算法】:http://blog.csdn.net/code_j_xer/article/details/51920134
【题目坑点1】:由于计算lcm(a, b)的中间过程需要计算a*b,虽然题目保证每个数不超过int表示范围,但是想成之后就会爆int,所以中间结果需要用long long类型来储存。
【AC代码】:

#include <cstdio>
#include <iostream>
#include <algorithm>

using namespace std;

int gcd(int a, int b){
    if(b == 0){
        return a;
    }
    return gcd(b, a % b);
}

int lcm(int a, int b){
    long long temp = (long long) a * (long long)b;
    return temp / gcd(a, b);
}

int main (){
    int m, n;
    scanf("%d", &m);
    while(m--){
        scanf("%d", &n);
            int n1;
            scanf("%d", &n1);
            n--;
            int ans = n1;
            while(n--){
                int n2;
                scanf("%d", &n2);
                ans = lcm(ans, n2);
            }
        printf("%d\n", ans);
    }
}

B:进制转换
http://acm.hdu.edu.cn/showproblem.php?pid=2031【hdu2031】

Problem Description
输入一个十进制数N,将它转换成R进制数输出。

Input 输入数据包含多个测试实例,每个测试实例包含两个整数N(32位整数)和R(2<=R<=16, R<>10)。

Output 为每个测试实例输出转换后的数,每个输出占一行。如果R大于10,则对应的数字规则参考16进制(比如,10用A表示,等等)。

Sample Input

7 2 23 12
-4 3

Sample Output

111 1B
-11

【题面大意】:讲一个给定的十进制数转换成R进制表示的数
【解法】:将给定的数不断地模进制数即可
【解题技巧】:
1:可先判断数的正负,若为负数先输出负号并且将原数转换成其相反数后再参与后续计算(避免模运算出错)。
2:n%R-10+’A’可将ABCDEF对应11,12,13,14,15,16
【AC代码】:

#include<cstdio>
#include<cstring>

int main ()
{
    int n, R, i, len;
    char ch;
    while(scanf("%d %d", &n, &R)!=EOF)
    {
        char a[100]={0};
        i = 0;
        if(n<0)
        {
            printf("-");
            n = -n;
        }
        while(n)
        {
            if(n%R>=10)
                ch = n%R-10+'A';
            else
                ch = n%R+'0';
            a[i] = ch;
            n /= R;
            i++;
        }
        len = strlen(a);
        for(i=0;i<len;i++)
            printf("%c",a[len-1-i]);
        printf("\n");
    }

    return 0;
}

C:三角形
http://acm.hdu.edu.cn/showproblem.php?pid=2039【hdu2039】

Problem Description
给定三条边,请你判断一下能不能组成一个三角形。

Input 输入数据第一行包含一个数M,接下有M行,每行一个实例,包含三个正数A,B,C。其中A,B,C <1000;

Output 对于每个测试实例,如果三条边长A,B,C能组成三角形的话,输出YES,否则NO。

Sample Input

2
1 2 3
2 2 2

Sample Output

NO
YES

【题面大意】:判断给定的3个数能不能组成三角形
【解法】:排序,小的两边之和大于最大的一边即可
【坑点】:题目并未限定边长为整形,所以边长可能为实数(double)
【AC代码】:

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

int main (){
    int m;
    double a[3];
    scanf("%d", &m);
    while(m--){
        scanf("%lf%lf%lf", &a[0], &a[1], &a[2]);
        sort(a, a + 3);
        if((a[0] + a[1] > a[2])){
            printf("YES\n");
        }
        else{
            printf("NO\n");
        }
    }
    return 0;
}

D:空心三角形
http://acm.hdu.edu.cn/showproblem.php?pid=2091【hdu2091】

Problem Description
把一个字符三角形掏空,就能节省材料成本,减轻重量,但关键是为了追求另一种视觉效果。在设计的过程中,需要给出各种花纹的材料和大小尺寸的三角形样板,通过电脑临时做出来,以便看看效果。

Input 每行包含一个字符和一个整数n,(0<n<41),不同的字符表示不同的花纹,整数n表示等腰三角形的高。显然其底边长为2n-1。如果遇到@字符,则表示所做出来的样板三角形已经够了

Output 每个样板三角形之间应空上一行,三角形的中间为空。显然行末没有多余的空格。

Sample Input

X 2
A 7
@

Sample Output
X
XXX
 
A
A A
A A
A A
A A
A A
AAAAAAAAAAAAA

【题面大意】:给定一个字符,用该字符打印出指定大小的空心三角形
【解法】:简单模拟
【坑点】:每个三角形之间有一个空行,最后一个三角形后无空行
【AC代码】:

#include <cstdio>
#include <iostream>
#include <algorithm>

using namespace std;

void printblack(int n){
    for(int i = 0; i < n; i++){
        printf(" ");
    }
}

int main (){
    char in[2];
    int  n;
    int term = 0;
    while(scanf("%s", in) != EOF && in[0] != '@'){
        term++;
        scanf("%d", &n);
        char ch = in[0];
        if(n == 1){
            if(term == 1){
                printf("%c\n", ch);
            }
            else{
                printf("\n%c\n", ch);
            }
        }
        else{
            if(term != 1){
                printf("\n");
            }

            printblack(n - 1);
            printf("%c", ch);
            printf("\n");

            for(int i = 1; i <= n - 2; i++){
                printblack(n - (i + 1));
                printf("%c", ch);
                printblack(2 * i - 1);
                printf("%c", ch);
                printf("\n");
            }

            for(int i = 0; i < 2 * n - 1; i++){
                printf("%c", ch);
            }
            printf("\n");
        }
    }
    return 0;
}

E:整数解
http://acm.hdu.edu.cn/showproblem.php?pid=2092【hdu2092】

Problem Description
有二个整数,它们加起来等于某个整数,乘起来又等于另一个整数,它们到底是真还是假,也就是这种整数到底存不存在,实在有点吃不准,你能快速回答吗?看来只能通过编程。 例如: x + y = 9,x * y = 15 ? 找不到这样的整数x和y 1+4=5,1*4=4,所以,加起来等于5,乘起来等于4的二个整数为1和4 7+(-8)=-1,7*(-8)=-56,所以,加起来等于-1,乘起来等于-56的二个整数为7和-8

Input 输入数据为成对出现的整数n,m(-10000<n,m<10000),它们分别表示整数的和与积,如果两者都为0,则输入结束。

Output 只需要对于每个n和m,输出“Yes”或者“No”,明确有还是没有这种整数就行了。

Sample Input

9 15
5 4
1 -56
0 0

Sample Output

No
Yes
Yes

【题面大意】:判断存不存在两个数,使它们加起来等于某个整数,乘起来又等于另一个整数。
【解法】:
给定:
x+y=n …..①
x*y =m …..②
则y = n - x …..③
将③带入②,得:
x*(n - x) = m …..④
利用求根公式求得④式的解,然后将求得的解带入原表达式,若原表达式成立则存在,若原表达式不成立则不存在。
【AC代码】:

#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

int main(){
    int n, m;
    while(scanf("%d%d", &n, &m) != EOF && (n || m)){
        int x1 = (n + sqrt(n * n - 4 * m)) / 2;
        int x2 = (n - sqrt(n * n - 4 * m)) / 2;
        if((x1 * x1 - n * x1 + m) == 0 || (x2 * x2 - n * x2 + m) == 0){
            printf("Yes\n");
        }
        else{
            printf("No\n");
        }
    }
}

F:考试排名
http://acm.hdu.edu.cn/showproblem.php?pid=2093【hdu2093】

Problem Description
C++编程考试使用的实时提交系统,具有即时获得成绩排名的特点。它的功能是怎么实现的呢? 我们做好了题目的解答,提交之后,要么“AC”,要么错误,不管怎样错法,总是给你记上一笔,表明你曾经有过一次错误提交,因而当你一旦提交该题“AC”后,就要与你算一算帐了,总共该题错误提交了几回。虽然你在题数上,大步地跃上了一个台阶,但是在耗时上要摊上你共花去的时间。特别是,曾经有过的错误提交,每次都要摊上一定的单位时间分。这样一来,你在做出的题数上,可能领先别人很多,但是,在做出同样题数的人群中,你可能会在耗时上处于排名的劣势。 例如:某次考试一共8题(A,B,C,D,E,F,G,H),每个人做的题都在对应的题号下有个数量标记,负数表示该学生在该题上有过的错误提交次数,但到现在还没有AC,正数表示AC所耗的时间,如果正数a跟上一对括号,里面有个整数b,那就表示该学生提交该题AC了,耗去了时间a,同时,曾经错误提交了b次,因此对于下述输入数据:

若每次错误提交的罚分为20分,则其排名从高到低应该是这样的: Josephus 5 376 John 4 284 Alice 4 352 Smith 3 167 Bob 2 325 Bush 0 0

Input 输入数据的第一行是考试题数n(1≤n≤12)以及单位罚分数m(10≤m≤20),每行数据描述一个学生的用户名(不多于10个字符的字串)以及对所有n道题的答题现状,其描述采用问题描述中的数量标记的格式,见上面的表格,提交次数总是小于100,AC所耗时间总是小于1000。

Output 将这些学生的考试现状,输出一个实时排名。实时排名显然先按AC题数的多少排,多的在前,再按时间分的多少排,少的在前,如果凑巧前两者都相等,则按名字的字典序排,小的在前。每个学生占一行,输出名字(10个字符宽),做出的题数(2个字符宽,右对齐)和时间分(4个字符宽,右对齐)。名字、题数和时间分相互之间有一个空格。

Sample Input

8 20
Smith -1 -16 8 0 0 120 39 0
John 116 -2 11 0 0 82 55(1) 0
Josephus 72(3) 126 10 -3 0 47 21(2) -2
Bush 0 -1 -8 0 0 0 0 0
Alice -2 67(2) 13 -1 0 133 79(1) -1
Bob 0 0 57(5) 0 0 168 -7 0

Sample Output

Josephus 5 376
John 4 284
Alice 4 352
Smith 3 167
Bob 2 325
Bush 0 0

因为每个同学的答题情况都有可能有WA的情况,所以都可能带有括号,所以不能直接当成数字读入,应该把所有数据都先按照字符串读入,然后判断是否有括号之后,再讲字符串形式的耗时转化成整形的耗时,所以这个题需要对字符串的操作比较熟悉:
1:截取子串
2:字符串和数字的转化atoi()函数和itoa()函数
【题面大意】:给一个榜(类似acm的),然后计算各个同学的排名
【解法】:处理出每个同学每道题的耗时,然后计算单个人的过题数以及总耗时,结构体排序
【AC代码】:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <algorithm>

using namespace std;

struct Person{
    string name;                        ///姓名
    string get[15];                     ///答题情况
    int subtime[15];                    ///单道题花的时间,算上罚时
    int time;                           ///转化后总的时间
    int num;                            ///AC的题目个数
}P[1050];

bool cmp(struct Person a, struct Person b){
    if(a.num == b.num){
        return a.time < b.time;
    }
    return a.num > b.num;
}

int main (){
    int n, m;
    int index = 0;
//    freopen("stdin.txt", "r", stdin);
    scanf("%d%d", &n, &m);
    while(cin >> P[index].name){
        for(int i = 0; i < n; i++){
            cin >> P[index].get[i];
        }
        index++;
    }

    for(int i = 0; i < index; i++){
        for(int j = 0; j < n; j++){
            if( *(P[i].get[j].end() - 1) == ')'){                               ///过了题
                int start = P[i].get[j].find('(');
                int end = P[i].get[j].find(')');
                int wa = atoi( P[i].get[j].substr(start + 1, end - start - 1).c_str() );
                int time1 = atoi(P[i].get[j].substr(0, start).c_str());
                P[i].subtime[j] = time1 + wa * m;
            }
            else{
                int time2 = atoi( P[i].get[j].c_str() );
                if(time2 <= 0){
                    P[i].subtime[j] = 0;
                }
                else{
                    P[i].subtime[j] = time2;
                }
            }
        }
    }

    for(int i = 0; i < index; i++){
        int sum = 0;
        int ans = 0;
        for(int j = 0 ; j < n; j++){
            if( P[i].subtime[j] > 0 ){
                ans++;
            }
            sum += P[i].subtime[j];
        }
        P[i].num = ans;
        P[i].time = sum;
    }

    sort(P, P + n, cmp);

    for(int i = 0; i < index; i++){
        printf("%-10s %2d %4d\n", P[i].name.c_str(), P[i].num, P[i].time);
    }

    return 0;
}

G:Olympiad
http://acm.hdu.edu.cn/showproblem.php?pid=5327【hdu5327】

Problem Description
You are one of the competitors of the Olympiad in numbers. The problem of this year relates to beatiful numbers. One integer is called beautiful if and only if all of its digitals are different (i.e. 12345 is beautiful, 11 is not beautiful and 100 is not beautiful). Every time you are asked to count how many beautiful numbers there are in the interval [a,b] (a≤b). Please be fast to get the gold medal!

Input The first line of the input is a single integer T (T≤1000), indicating the number of testcases.

For each test case, there are two numbers a and b, as described in the statement. It is guaranteed that 1≤a≤b≤100000.

Output For each testcase, print one line indicating the answer.

Sample Input

2 1 10 1 1000

Sample Output

10 738

前缀的思想。最多有1000组查询, 每次查询可能跨越的区间大小是100000,所以暴力会TLE,由于这道题的特性,每个数要么是漂亮数,要么不是,询问的是一段区间内的漂亮数,故可以预处理出前缀和数组,O(1)处理每次询问
【题面大意】:每位数码都不同的数叫做漂亮数。T次询问,某一区间内有多少个漂亮数。
【解法】:处理出前缀和数组sum_beatiful,则区间[a, b]内的漂亮数如下:sum_beatiful[b] - sum_beatiful[a - 1]
【AC代码】:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define NMAX 100005

using namespace std;

bool is_beatiful[NMAX] = {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
int sum_beatiful[NMAX];
int time[15];

bool judge(int a){
    memset(time, 0, sizeof(time));
    while(a){
        time[a % 10]++;
        a /= 10;
    }
    int ans = 1;
    for(int i = 0; i < 10; i++){
        if(time[i] > 1){
            ans = 0;
            break;
        }
    }
    return ans;
}

int main(){
    for(int i = 11; i <= 100000; i++){
        is_beatiful[i] = judge(i);
    }
    for(int i = 1; i <= 100000; i++){
        sum_beatiful[i] = is_beatiful[i] + sum_beatiful[i - 1];
    }
    int T, a, b;
    scanf("%d", &T);
    while(T--){
        scanf("%d%d", &a, &b);
        printf("%d\n", sum_beatiful[b] - sum_beatiful[a - 1]);
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值