SICNU 2018 Summer Training #2

Posted maybe96

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SICNU 2018 Summer Training #2相关的知识,希望对你有一定的参考价值。

   这场比赛感觉起来还是比较基础的吧,一半多的题目应该都是可以做的,但是还是太菜了,只做了5题。。也是因为时间比较赶有几题过题少的都没看题

b题在比赛的时候没做出来,wa了几次就转其他题目了,思路应该比较常规,就是纸上模拟找下规律,因为数据比较大所以也不能直接模拟,规律应该就是如果第一行可以放满,就每个人都有一个,然后分奇偶

如果是偶数行数就前面n-1个可以得到糖果,否则就是后面n-1个可以得到糖果,然后其实就是中间的不影响,只是第一个和最后一个是减半的,而且根据奇偶要-1或者不变,然后就模拟最后一行就好了,然后特判一下没排满第一行的情况就行了。

c题题意一开始没读懂,以为是n&(n-1)的情况,然后wa了,后面Google翻译了一下就是二进制翻转,找小于他本身的最大的那个数,其实就是找1了,如果找到了第一个1,就翻转就行了,最后输出1的位数

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <set>
#include <map>
#include <string>
using namespace std;

int main()
{
    int t;
    int n,m;
    int s[10000];
    cin>>t;
    while(t--){
        cin>>n;
        int a=0;
        m=0;
        while(n>0){
            s[a++]=n%2;
            n/=2;
        }
        for(int i=0;i<a;i++){
            m++;
            if(s[i]==1) break;
        }
        cout<<m<<endl;
    }
    return 0;
}

然后是D题,实质上就是找规律,如果n==m 就很好办,正方形经过所以块的边就是n*(n+1)/2,否则就必须分n和m的奇偶情况

如果奇偶性相同就是跟相同的情况相似,只不过有两种情况就是取两种情况的最小m*(n+1)/2

如果奇偶性不同,就需要对折,然后与直接的m*(n+1)/2,进行比较

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <set>
#include <map>
#include <cstring>
using namespace std;
    int cmp(int x,int y){
        return x>y;
    }
int main() {
    int t;
    long long n,m;
    cin>>t;
    while(t--){
        cin>>n>>m;
        if(n==m){
            cout<<n*(n+1)/2<<endl;
        }
        else{
            long long s;
            if(n%2==0&&m%2==0) s=min(n*(m+1)/2,m*(n+1)/2);
            else if(n%2==1&&m%2==0) s=min(m*(n/2+1)/2+(m/2+1)*(n/2),m*(n+1)/2);
            else if(n%2==0&&m%2==1) s=min((m/2+1)*n/2+(m/2)*(n/2+1),n*(m+1)/2);
            else s=min((n+1)*m/2,(m+1)*n/2);
            cout<<s<<endl;
        }
    }
    return 0;
}

f题思路挺好想的,就是贪心,先用map存,排序从大到小进行判断,每个数从1到平方根判断是否能被整除,如果能,再判断两个因数是否在map里,如果小因数在,就直接break,如果大因数在就需要继续判断是否还有比这个因数小的存在,思路和实现没太大的问题,主要是这题有点卡时间,一开始一直tle,不断修改,也不知道哪里有问题,后来发现使用cin和cout进行输入和输出是不行的,要使用printf或者scanf,或者取消流同步,然后就是在两个因数的判断上可能存在一些易错点

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <set>
#include <map>
#include <cstring>
using namespace std;
    int cmp(int x,int y){
        return x>y;
    }
int main()
{
    int t;
    scanf("%d",&t);
    int n,m;
    int num[100005];
    map<int,int>s;
    while(t--){
        long long sum=0;
        s.clear();
        scanf("%d",&n);
        for(int i=0;i<n;i++) {
            scanf("%d",&num[i]);
            s[num[i]]=1;
        }
        sort(num,num+n,cmp);
        for(int i=0;i<n;i++){
            int t=0;
            int ss=0;
            for(int j=1;j<=sqrt(num[i]);j++){
                if(num[i]%j==0){
                    if(s[j]!=0){
                        num[i]=j;
                        t=0;
                        break;
                    }
                    else if(s[num[i]/j]){
                        ss=num[i]/j;
                        t=1;
                    }
                }
            }
            if(t==1) num[i]=ss;
            sum+=num[i];
        }
        printf("%lld
",sum);
    }
    return 0;
}

h题应该是个签到题,挺简单的,O(N)复杂度找前后两数和的最大值

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <set>
#include <map>
#include <string>
using namespace std;

int main()
{
    int n,m;
    int num[2005];
    int t;
    cin>>t;
    while(t--){
        cin>>n;
        int maxn=-1;
        for(int i=0;i<2*n;i++) cin>>num[i];
        for(int i=0;i<n;i++){
            maxn=max(maxn,num[i]+num[2*n-i-1]);
        }
        cout<<maxn<<endl;
    }
    return 0;
}

i题应该也是签到题

大意就是给一个数,然后告诉需要划分几份,找最平均的划分(最大值与最小值的差最小)

其实就是两种情况,一直是只有n/m的情况,一种就是有n/m和n/m+1的情况

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <set>
#include <map>
#include <string>
using namespace std;

int main()
{
    int n,m;
    int t;
    cin>>t;
    while(t--){
        cin>>n>>m;
        if(m>n){
            cout<<-1<<endl;
            continue;
        }
        if(m==n){
            for(int i=0;i<n;i++){
                if(i!=0) cout<< ;
                cout<<1;
            }
        }
        else{
            if(n%m==0){
                for(int i=0;i<m;i++){
                if(i!=0) cout<< ;
                cout<<n/m;
            }
            }
            else {
                int t=n/m;
                int s=n-t*m;
                for(int i=0;i<m-s;i++){
                    if(i!=0) cout<< ;
                    cout<<t;
                }
                for(int i=0;i<s;i++) cout<< <<t+1;
            }
        }
        cout<<endl;
        }
    return 0;
}

 

 

 

以上是关于SICNU 2018 Summer Training #2的主要内容,如果未能解决你的问题,请参考以下文章

sicnu 区域赛选拔赛

ECJTU 2018 Summer Training 2

MYGE 2018 SPRING/SUMMER COLLECTION

集训实录2018_XDU_ACM_SUMMER_TRAINING

Deep Learning and Reinforcement Learning Summer School 2018

2018-2019 Summer Petrozavodsk Camp, Oleksandr Kulkov Contest 2解题报告