Educational Codeforces Round 7总结

A题:

A题题目链接

题目描述:

A. Infinite Sequence
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

Consider the infinite sequence of integers: 1, 1, 2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4, 5.... The sequence is built in the following way: at first the number 1 is written out, then the numbers from 1 to 2, then the numbers from 1 to 3, then the numbers from 1 to 4 and so on. Note that the sequence contains numbers, not digits. For example number 10 first appears in the sequence in position 55 (the elements are numerated from one).

Find the number on the n-th position of the sequence.

Input

The only line contains integer n (1 ≤ n ≤ 1014) — the position of the number to find.

Note that the given number is too large, so you should use 64-bit integer type to store it. In C++ you can use the long long integer type and in Java you can use long integer type.

Output

Print the element in the n-th position of the sequence (the elements are numerated from one).

Sample test(s)
input
3
output
2
input
5
output
2
input
10
output
4
input
55
output
10
input
56
output
1

题意:

给定一个数列,数列的规律是1,1,2,1,2,3,1,2,3,4....的形式依次递增,问这个数列中第n个数是多少?(1<=n<=10^14)

解析:

一开始我看到n的量级达到了10^14,所以我就没往暴力遍历的方向上去想,于是就开始寻找一般规律,然后发现这个其实就是解一个一元二次方程的正整数解(根据等差数列前n项和的公式),相当于前n-1个整数块都是完整的,然后n减去前n-1个完整的整数块,得到不完整的整数块遍历到的数字。如果这个一元二次方程的解是相同的,那么说明刚好到达第n个整数块的末尾,然后输出这个解即可。

完整代码实现:

#include<cstdio>
#include<algorithm>
#include<cmath>
typedef long long ll;
int main()
{
    ll n;
    while(scanf("%I64d",&n)==1)
    {
         ll flag = (sqrt(8*n+1) - 1) / 2;
         //printf("flag = %I64d\n",flag);
         if(ll(sqrt(8*n+1)) * ll(sqrt(8*n+1)) == 8*n+1)
         {
             printf("%I64d\n",flag);
         }
         else
         {
             ll all_pre = (flag + 1) * flag / 2;
             printf("%I64d\n",n-all_pre);
         }

    }
    return 0;
}

需要注意的一个问题是:在if判断中左边的表达式sqrt()函数的返回值是浮点型的,而右边表达式的值是长整型,不同编译器处理可能会出现不同的问题,因此需要对左边sqrt()的返回值进行强制转换。

然后我发现别人都是用直接暴力的方法一个个遍历过去,于是我自己也尝试了,发现并没有超时,下面是测试:


所以在以后有想法的时候,可以用大数据测试一下,并用计算机计算一下运行时间,若未超时,即可提交。

完整代码实现:

#include<cstdio>
//#include<ctime>
#include<iostream>
//using namespace std;
typedef long long ll;
int main()
{
    ll n;
    //int start,finish;
    while(scanf("%I64d",&n)==1)
    {
        int i = 0;
        //start = clock();
        while(n > i)
        {
            n -= i;
            i++;
        }
        //finish = clock();
        //cout << finish - start << "ms" <<endl;  //(以毫秒为计时单位)
        printf("%I64d\n",n);
    }

    return 0;
}
B题:
B题题目链接
题目描述:

B. The Time
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

You are given the current time in 24-hour format hh:mm. Find and print the time after a minutes.

Note that you should find only the time after a minutes, see the examples to clarify the problem statement.

You can read more about 24-hour format here https://en.wikipedia.org/wiki/24-hour_clock.

Input

The first line contains the current time in the format hh:mm (0 ≤ hh < 24, 0 ≤ mm < 60). The hours and the minutes are given with two digits (the hours or the minutes less than 10 are given with the leading zeroes).

The second line contains integer a (0 ≤ a ≤ 104) — the number of the minutes passed.

Output

The only line should contain the time after a minutes in the format described in the input. Note that you should print exactly two digits for the hours and the minutes (add leading zeroes to the numbers if needed).

See the examples to check the input/output format.

Sample test(s)
input
23:59
10
output
00:09
input
20:20
121
output
22:21
input
10:10
0
output
10:10

题意:

给定一个时间,然后按照给定格式输出a分钟后的时间

解析:

这道题是一道水题,只要按照题目要求,并且分类讨论即可

完整代码实现:

#include<cstdio>
#include<algorithm>
using namespace std;
int main()
{
    int old_hour,old_minute,a,new_hour,new_minute;
    while(scanf("%d:%d%d",&old_hour,&old_minute,&a)==3)
    {
        int hour,minute;
        hour = a / 60;
        minute = a % 60;
        new_minute = (old_minute + minute) % 60;
        new_hour = (old_hour + hour + (old_minute + minute) / 60) % 24;
        if(new_hour < 10 && new_minute >= 10)
        {
            printf("0%d:%d\n",new_hour,new_minute);
        }
        else if(new_hour >= 10 && new_minute < 10)
        {
            printf("%d:0%d\n",new_hour,new_minute);
        }
        else if(new_hour >= 10 && new_minute >= 10)
        {
            printf("%d:%d\n",new_hour,new_minute);
        }
        else if(new_hour < 10 && new_minute < 10)
        {
            printf("0%d:0%d\n",new_hour,new_minute);
        }
    }
    return 0;
}
C题:

C题题目链接
题目描述:

C. Not Equal on a Segment
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

You are given array a with n integers and m queries. The i-th query is given with three integers li, ri, xi.

For the i-th query find any position pi (li ≤ pi ≤ ri) so that api ≠ xi.

Input

The first line contains two integers n, m (1 ≤ n, m ≤ 2·105) — the number of elements in a and the number of queries.

The second line contains n integers ai (1 ≤ ai ≤ 106) — the elements of the array a.

Each of the next m lines contains three integers li, ri, xi (1 ≤ li ≤ ri ≤ n, 1 ≤ xi ≤ 106) — the parameters of the i-th query.

Output

Print m lines. On the i-th line print integer pi — the position of any number not equal to xi in segment [li, ri] or the value  - 1 if there is no such number.

Sample test(s)
input
6 4
1 2 1 1 3 5
1 4 1
2 6 2
3 4 1
3 4 2
output
2
6
-1
4
题意:

给定一个两个整数n,m,分别表示数组中元素的个数以及询问的次数,然后接下来的一行是数组a中的n个元素,编号从1开始,接着接下来的四行,每行三个整数,前两个整数是区间范围,左闭右闭,第三个整数是查询的数字x,问在给定区间内,输出任意一个不等于x的元素的下标,若不存在,则输出-1.

解析:

这是一道典型的预处理优化的题目,我们可以先将结果离线处理,并且保存在另外一个重新申请的数组中,然后再一次性输出。

由于是输出任意一个不等于x的元素的下标,因此我们可以通过区间的边界入手,一开始我们可以统计好,在给定数组中,每个数右边第一个不等于该数的元素的下标,然后存储起来,但是需要注意的问题是,如果我们正序统计的话,必然会有很多重复的操作,这样的话,在大量数据的情况下可能会超时例如:

第一个数是1,第二个数也是1,那么从第二个数找到其右边第一个不等于该数的元素的下标就是重复遍历的。

因此我们想到逆序来寻找,这样的话当我们从最后一个数开始寻找的时候,如果前一个数和后一个数相等,那么它们右边第一个不等于该数的元素的下标是相同的。

然后离线处理完毕后,比较a[l]和x,如果不等,则直接输出l,否则的话,则是a[l]==x了,那么这样的话,我们就用预处理好的结果,通过a[l]右边第一个不等于该数的元素的下标与区间的右端点的比较,如果该元素下标大于区间右端点的值,则表示“越界”,则输出-1,反之则输出该元素下标。

需要注意的是:数组最后一个元素右边的数不存在,所以要在预处理的数组中,将b[n]预置成一个很大的数字(至少要大于数组a中元素下标的最大值)

完整代码实现:

#include<cstdio>
#include<algorithm>
const int maxn = 2e5;
const int INF = 0x3f3f3f3f;
int a[maxn+20],b[maxn+20];
int main()
{
    int n,m;
    while(scanf("%d %d",&n,&m) == 2 && n && m)
    {
        int l,r,x;
        for(int i = 1;i <= n;i++)
            scanf("%d",&a[i]);
        b[n] = INF;    //最右边的数的右边不存在与其不等的数
        for(int i = n - 1;i>=1;i--)
        {
            if(a[i+1]!=a[i])   b[i] = i+1;
            else    b[i] = b[i+1];
        }
        while(m--)
        {
            scanf("%d %d %d",&l,&r,&x);
            if(a[l] != x)   printf("%d\n",l);
            else
            {
                printf("%d\n",b[l] <= r ? b[l] :-1);
            }
        }
    }
    return 0;
}

D题:

D题题目链接

题目描述:

D. Optimal Number Permutation
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

You have array a that contains all integers from 1 to n twice. You can arbitrary permute any numbers in a.

Let number i be in positions xi, yi (xi < yi) in the permuted array a. Let's define the value di = yi - xi — the distance between the positions of the number i. Permute the numbers in array a to minimize the value of the sum .

Input

The only line contains integer n (1 ≤ n ≤ 5·105).

Output

Print 2n integers — the permuted array a that minimizes the value of the sum s.

Sample test(s)
input
2
output
1 1 2 2
input
1
output
1 1
题意:

给定一个数n,然后输出一个数列,数列中的元素包括所有的从1-n的数两次,数列中的数可以任意排列,但是要满足.,使得s的值最小。

解析:

这是一道构造题,百度百科对于构造法的描述:

数学——构造法

首先我们从问题入手,既然要使得s的值最小,那么我们便从表达式入手,发现s最小值可以为0,需满足以下两种情况:

1.n的值与i相等

2.di + i - n = 0,即di应该等于n-i;

所以我们可以根据以上的要求,枚举出前五项的数列:

当n=1时,数列为    1    1

当n=2时,数列为    1    1    2    2

当n=3时,数列为    1    3    1    2    2    3

当n=4时,数列为    1    3    3    1    2    4    2    4

当n=5时,数列为    1    3    5    3    1    2    4    4    2    5

当枚举到第五项的时候,规律已经很明显了,因此我们可以分奇偶的情况得出以下完整代码:

#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 5e5+5;
int num[maxn<<1];
int main()
{
    int n;
    while(scanf("%d",&n)==1&&n)
    {
        int j = 1;
        num[2*n] = n;   //无论奇偶,最后一个数均为最大的数
        if(n%2!=0)    //n为奇数时
        {
            for(int i = 1;i <= n;i=i+2,j++)
                num[j] = i;
            for(int i = n-2;i >=1;i=i-2,j++)
                num[j] = i;
            for(int i = 2;i <=n-1;i=i+2,j++)
                num[j] = i;
            for(int i = n-1;i >=2;i=i-2,j++)
                num[j] = i;
        }
        else
        {
            for(int i = 1;i <= n-1;i=i+2,j++)
                num[j] = i;
            for(int i = n-1;i >=1;i=i-2,j++)
                num[j] = i;
            for(int i = 2;i <=n;i=i+2,j++)
                num[j] = i;
            for(int i = n-2;i >=2;i=i-2,j++)
                num[j] = i;
        }
        for(int i = 1;i <=2*n;i++)
        {
            if(i==1)    printf("%d",num[i]);
            else        printf(" %d",num[i]);
        }
        printf("\n");
    }
    return 0;
}

本次总结:这次Educational round是数学场,几道题目基本上都是数学思维去做的,但是作为数学题,需要把握一个很重要的东西,那就是把实际问题转换成数学模型去求解,还有就是要自己观察出给定题意的规律,就像是本次比赛的D题,输出数列的结果可能有多种,但是我们要的是能够得出一般规律的数列,所以我们在有多种输出的情况下,找出最有规律或者说与上下结合紧密的那一组,这样的话更有利于我们找出一般性的规律

多练习,多思考。(C题,D题均为好题)

如有错误,还请指正,O(∩_∩)O谢谢

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值