SDUT 2021 Spring Individual Contest(for 20) - 14(补题)

Posted 佐鼬Jun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SDUT 2021 Spring Individual Contest(for 20) - 14(补题)相关的知识,希望对你有一定的参考价值。

Gaby And Addition

Gaby is a little baby who loves playing with numbers. Recently she has learned how to add 2 numbers using the standard addition algorithm which we summarize in 3 steps:
1.Line up the numbers vertically matching digits places.
2.Add together the numbers that share the same place value from right to left.
3.Carry if necessary.
it means when adding two numbers we will get something like this:
Unfortunately as Gaby is too young she doesn’t know what the third step means so she just omitted this step using her own standard algorithm (Gaby’s addition algorithm). When adding two numbers without carrying when necessary she gets something like the following:

Gaby loves playing with numbers so she wants to practice the algorithm she has just learned (in the way she learned it) with a list of numbers adding every possible pair looking for the pair which generates the largest value and the smallest one.

She needs to check if she is doing it correctly so she asks for your help to find the largest and the smallest value generated from the list of numbers using Gaby’s addition algorithm.

Input
The input starts with an integer n (2 ≤ n ≤ 106) indicating the number of integers Gaby will be playing with. The next line contains n numbers ni (0 ≤ ni ≤ 1018) separated by a single space.

Output
Output the smallest and the largest number you can get from adding two numbers from the list using Gaby’s addition algorithm.

Examples
Input

6
17 5 11 0 42 99
Output
0 99
Input
7
506823119072235413 991096248449924896 204242310783332529 778958050378192979 384042493592684633 942496553147499866 410043616343857825
Output
52990443860776502 972190360051424498
Note
In the first sample input this is how you get the minimum and the maximum value
题意: 就是给n个数进行不进位加法运算,问你算出来的最大数和最小数
思路: 利用字典树,把一长串数存放在字典树,进行加法运算时,找出能算出来的最大数和最小数。用字符串来存这些数,再模拟不进位加法的会超时,所以要用字典树降低时间复杂度。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e7+3000000;
const int M=1e6+10;
#define inf 0x3f3f3f3f3f3f3f3f
ll a[M],tree[N][10],b[100]; //a是读入的数,tree就是字典树,b是存分解后的数
ll flag,idx;
void insert(ll x){ //字典树存数操作
    for(int i=0;i<=18;i++){
        b[i]=x%10;
        x/=10;
    }
    int p=0;
    for(int i=18;i>=0;i--){
        int u=b[i];
        if(tree[p][u]==0) tree[p][u]=++idx;
        p=tree[p][u];
    }
    
}
ll find1(ll x){  //找最大值
    ll sum=0;
    for(int i=0;i<=18;i++){ //把数分解
        b[i]=x%10;
        x/=10;
    }
    int p=0;
    for(int i=18;i>=0;i--){ 
        ll mx=-1;
        for(int j=0;j<=9;j++){
            if(tree[p][j]&&mx<(b[i]+j)%10){ //这个数存在,且j+这个数是最大的,就选择这个数
                mx=(b[i]+j)%10;
                flag=j;
            }
        }
        sum=sum*10+mx; //把最大的那个数还原出来
        p=tree[p][flag];
    }
    return sum;
}
ll find2(ll x){ //找最小的数,原理同上
    ll sum=0;
    for(int i=0;i<=18;i++){
        b[i]=x%10;
        x/=10;
    }
    int p=0;
    for(ll i=18;i>=0;i--){
        ll mx=20;
        for(ll j=0;j<=9;j++){
            if(tree[p][j]&&mx>(b[i]+j)%10){
                mx=(b[i]+j)%10;
                flag=j;
            }
        }
        sum=sum*10+mx;
        p=tree[p][flag];
    }
    return sum;
}
int main(){
    int n;
    ll maxx=0,minn=inf;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
        if(i>1){ //只有一个数,也无法进行运算
            maxx=max(maxx,find1(a[i]));
            minn=min(minn,find2(a[i]));
        }
        insert(a[i]); //先求和找最值,在插入新数据,是为了避免自己和自己相加
       
    }
    printf("%lld %lld\\n",minn,maxx);
    return 0;
}

Planet Communcation

Lately the communication between planets has been an important issue, which is why the Earth has made many efforts to be connected to every other planet in the universe.

The Universal Network Army of Lasers (UNAL) is trying to connect the Earth with other planets in the universe. In order to make this, the UNAL uses a laser machine which each time it is used, it sends a communication signal in the form of a ray of light in the direction of the planet.

This laser machine is so powerful, that a ray of light generated by it is capable to cross all the planets it touches until the end of the universe. Moreover, when it fires a ray of light in one direction it also fires a ray of light in the opposite direction.

Given the coordinates of all the planets in the universe, help the UNAL to design the way to communicate the Earth with all other planets in the universe using the machine the minimum number of times.

Input
The first line of input contains one integer n (1 ≤ n ≤ 5000), the number of planets.

The next n lines contains the list of coordinates of the planets. In particular, the i - th line contains three integers xi, yi, zi ( - 109 ≤ xi, yi, zi ≤ 109), the coordinates of the i - th planet, respectively. The Earth is the first planet on the list. It is guaranteed that all the planets have different coordinates.

Output
Output a single integer, the minimun number of times the machine should be used to communicate the Earth with all other planets in the universe

Examples
Input

3
0 0 0
1 1 0
-1 -1 0
Output
1
Input
4
0 0 0
1 0 0
0 1 0
0 0 1
Output
3
题意: 就是给你一个地球点(第一个就是),再给你其他星球的坐标,给你个照射无线长的光(光是会照过去,再回来的,无限长),问你要用这个光几次才能从地球开始遍历所有的星球。
思路: 就是有哪些点在一条直线上(把空间向量化简到最简形式,只要一样就是一条直线上),一条直线上的用map存起来,最后看map里面存了几个空间向量。
当然也可以暴力做,不用map,也不用化简,直接用两向量平行公式,用两重循环来做。
下面是一位大佬暴力做法的链接,我也是从中学到了不少
链接: link.
下面附上map存空间向量的做法。

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#include<map>
#define ll long long
const int N=1e4+10;
struct node{
    ll x,y,z;
    bool operator<(const node &a) const{ //要加重载,保证在map里的排序,否则会wa
        if(a.x==x) {
            if(a.y==y){
                return a.z<z;
            }
            else return a.y<y;
        }
        return a.x<x;
    }
}a;
map<node,int> m;
int main(){
    int n;
    scanf("%d",&n);
    ll sx,sy,sz;
    scanf("%lld%lld%lld",&sx,&sy,&sz);
    for(int i=1;i<n;i++){
        scanf("%lld%lld%lld",&a.x,&a.y,&a.z);
        a.x-=sx; //算空间向量
        a.y-=sy;
        a.z-=sz;
        if(a.x<0){ //这里是为了统一所有空间向量的正负号
            a.x=-a.x,a.y=-a.y,a.z=-a.z;
        }
        else if(a.x==0){ //作用:同上
            if(a.y<0){
               a.y=-a.y,a.z=-a.z;
            }
        }
        else if(a.y==0){//同上
            if(a.z<0){
               a.z=-a.z;
            }
        }
        ll t=__gcd(abs(a.x),abs(a.y)); //化简成最小形式
        t=__gcd(t,abs(a.z));
        a.x/=t;
        a.y/=t;
        a.z/=t;
        m[a]++; //存到map中,只要最简形式一样就是平行
    }
    printf("%d\\n",m.size());
    return 0;
}

Text Editor

One of the most useful tools nowadays are text editors, their use is so important that the Unique Natural Advanced Language (UNAL) organization has studied many of the benefits working with them.

They are interested specifically in the feature “find”, that option looks when a pattern occurs in a text, furthermore, it counts the number of times the pattern occurs in a text. The tool is so well designed that while writing each character of the pattern it updates the number of times that the corresponding prefix of the total pattern appears on the text.

Now the UNAL is working with the editor, finding patterns in some texts, however, they realize that many of the patterns appear just very few times in the corresponding texts, as they really want to see more number of appearances of the patterns in the texts, they put a lower bound on the minimum number of times the pattern should be found in the text and use only prefixes of the original pattern. On the other hand, the UNAL is very picky about language, so they will just use the largest non-empty prefix of the original pattern that fit into the bound.

Input
The first line contains the text A (1 ≤ |A| ≤  105) The second line contains the original pattern B (1 ≤ |B| ≤  |A|) The third line contains an integer n (1 ≤ n ≤  |A|) - the minimum number of times a pattern should be found on the text.

Output
A single line, with the prefix of the original pattern used by the UNAL, if there is no such prefix then print “IMPOSSIBLE” (without the quotes)

Examples
Input

aaaaa
aaa
4
Output
aa
Input
programming
unal
1
Output
IMPOSSIBLE
Input
abracadabra
abra
1
Output
abra
Input
Hello World!
H W
5
Output
IMPOSSIBLE
题意:就是给你一个文本字符串,再给一个匹配字符串,然后给你最小匹配次数,然后你要输出匹配次数符合题意的匹配字符串前缀。
思路: 二分+KMP,利用kmp来进行匹配操作,求匹配次数。
二分是为了降低时间复杂度,二分的是匹配字符串的长度。最后就记录二分出来的长度,然后根据长度,把匹配字符串输出出来。
如果用暴力来一个一个从len往下减去1,匹配字符串前缀的长度,直到符合条件,那么时间复杂度最坏可能会出现O(n)这仅仅是匹配的循环,再乘上kmp的时间复杂度会超时。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
#define ll long long
const int N=1e6+10;
int Next[N];
char s1[N],s2[N];
int k;
int len1,len2;
void get_next(int len2){  //求next数组
    int i=0,j=-1;
    Next[0]=-1;
    while(i<len2){
        if(j==-1||s2[i]==s2[j]){
            i++,j++;
            Next[i]=j;
        }
        else j=Next[j];
    }
}
int KMP(int len1,int len){ //经典KMP的稍微变形
     int i=0,j=0;
     int cnt=0;
     while(i<len1){
         if(j==-1||s1[i]==s2[j]){
             i++,j++;
         }
         else j=Next[j];
         if(j==len){
             cnt++;
             j=Next[j];
         }
     }
     return cnt;
}
int main(){
    cin.getline(s1,N);
    cin.getline(s2,N);
    cin>>k;
    int len1=strlen(s1),len2=strlen(s2);
    get_next(len2);
    int l=0,r=len2;
    while(l<r){ 
        int mid=(l+r+1)>>1;
        int x=KMP(len1,mid);
        if(x>=k) l=mid; //匹配次数符合条件就缩小范围,增大匹配字符串长度
        else r=mid-1; //匹配次数不够,就放大范围,减小匹配字符串的长度
    }
    if(l==0) puts("IMPOSSIBLE"); //没匹配到
    else{
        for(int i=0;i<l;i++){ //根据长度来输出匹配字符串的前缀
            cout<<s2[i];
        }
        printf("\\n");
    }
    return 0;
}

Jeronimo’s List

Jeronimo the bear loves numbers and he is planning to write n numbers in his notebook.

After writing the first m numbers, Jeronimo felt that he was spending a lot of time thinking new numbers, so he wrote the next n - m missing numbers as the sum modulo 3 × 107 of the numbers in the i - m and i - m + 1 positions for m < i ≤ n

While Jeronimo was writing, his sister Lupe arrived and asked him q questions. The i - th question consist of a number bi, Jeronimo has to say what would be the number in the position bi if all the numbers were sorted in ascending order. Jeronimo wants to answer each question as soon as possible but he spends a lot of time counting so he ask your help.

Input
The first line of the input has three integers n (3 ≤ n ≤ 3 × 107), m (3 ≤ m ≤ min(100, n)) and q (1 ≤ q ≤ 10000).

The second line contains m numbers a1, a2, …, am, (0 ≤ ai < 3 × 107), The first m numbers that Jeronimo wrote.

The third line contains q questions b1, b2, …, bq (1 ≤ bi ≤ n)

Output
Print q lines. The i - th line must be the answer of the i - th question made by Lupe.

Examples
Input
6 3 6
1 2 3
1 2 3 4 5 6
Output
1
2
3
3
5
6
Input
10 4 3
1 2 9 10
1 5 10
Output
1
10
30
题意: 总共n个数字,先给你m个数字,剩下n-m个数字按照第i-m个+第i-m+1个数字再mod3×107,再按照升序排序,再给你q次询问,问第i个数字是什么。(一开始看英文题目,着实没看懂题目,导致无从下手)
思路: 把出现的数字统统放在桶里,然后按照升序,把数字放在新数组中,最后按照顺序,输出询问的数字。

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=3e7+10;
const int mod=3e7;
int a[N],b[N],c[N];
int n,m,q;
int main(){
    scanf("%d%d%d",&n,&m,&q);
    for(int i=1;i<=m;i++) {
        scanf("%d",&a[i]);
        c[a[i]]++; //存在桶里
    }
    for(int i=m+1;i<=n;i++){
        a[i]=(a[i-m]+a[i-m+1])%mod;
        c[a[i]]++;
    }
    int k=0;
    for(int i=0;i<mod;i++){
        for(int j=1;j<=c[i];j++){
            b[++k]=i; //把存在桶里的数,按照顺序排好
        }
    }
    while(q--){
        int x;
        scanf("%d",&x);
        printf("%d\\n",b[x]); //输出第x个数字
    }
    return 0;
}

To be continued
如果你有任何建议或者批评和补充,请留言指出,不胜感激

以上是关于SDUT 2021 Spring Individual Contest(for 20) - 14(补题)的主要内容,如果未能解决你的问题,请参考以下文章

SDUT 2021 Spring Individual Contest(for 20) - 1补题

SDUT 2021 Spring Individual Contest(for 20) - 17(补题)

SDUT 2021 Spring Individual Contest(for 20) - 15(补题)

SDUT 2021 Summer Individual Contest - 2(for 20)(补题)

SDUT 2021 Winter Individual Contest - N(B-Derangement)

2021-08-03SDUT 2021 Summer Individual Contest - 4(for 20)(补题)