Codeforces Round #708 (Div. 2)(A~C)

本次终于A了3题(c-1,c-2就算一题啦)

  1. Meximization

先去重,然后对前面不重复的部分排序,后面的顺序任意即可。一开始用了unique。

后来才发现他并不是前面不重复,将重复的放在后面,而是将前面重复的用后面不重复的元素替换了。固不能用unique,因为数据小,就也没多想,用vis记录是否重复,用temp记录重复的数即可。

AC代码如下:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
using namespace std;
int t,n,a[105],vis[105],temp[105];
int main(){
    scanf("%d",&t);
    while(t--){
        memset(vis,0,sizeof(vis));
        memset(temp,0,sizeof(temp));
        int cnt=0;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            scanf("%d",&a[i]);
        int temp[105];
        sort(a,a+n);
        for(int i=0;i<n;i++){
            if(!vis[a[i]]){
                printf("%d ",a[i]);
                vis[a[i]]=1;
            }else
                temp[cnt++]=a[i];
        }
        for(int i=0;i<cnt;i++)
            printf("%d ",temp[i]);
        printf("\n");
    }
    return 0;
}

B.M-arrays

  题意:将n个数任意分组,其中满足相邻两个数相加能整除m。求最少分组数

我们可以发现如果要满足要求,则相邻两个数相加模m=0.故对n个数各自模m。

然后记录。若m是8,则将模8=1和模8=7的数组合。如果相等或者相差为1例如171

就可以容纳在一个组,但如果是17111,就必须分三个组。因为171,1,1.

故先模m预处理后,记录模数的出现次数进行判断即可。

AC代码如下:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#define MAXN 100005 
using namespace std;
int t,n,m,a[MAXN],vis[MAXN];
int main(){
    scanf("%d",&t);
    while(t--){
        int ans=0;
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++){
            scanf("%d",&a[i]);
            a[i]%=m;
            vis[a[i]]++;
        }
        if(vis[0])
            ans++;
        vis[0]=0;
        for(int i=1;i<m;i++){
            if(vis[i]&&vis[m-i]){
                ans++;
                if(vis[i]==vis[m-i])
                    vis[i]=vis[m-i]=0;
                else if(vis[i]>vis[m-i]){
                    vis[i]-=vis[m-i]+1;
                    vis[m-i]=0;
                    ans+=vis[i];
                    vis[i]=0;
                }else{
                    vis[m-i]-=vis[i]+1;
                    vis[i]=0;
                    ans+=vis[m-i];
                    vis[m-i]=0;
                }
            }else if(vis[i]){
                ans+=vis[i];
                vis[i]=0;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

C1. k-LCM (easy version)

    给定n和k。求出k个数满足a1+~+ak=n,lcm(a1,a2~,ak)<=n/2.

在easy version中k等于3.

       首先我们观察到当n为奇数时,我们可以拆成1,n/2,n/2。(lcm为n/2)

       当n为偶数且不是4的倍数时,拆成2,n/2-1,n/2-1.(lcm为n/2-1)

       当n为4的倍数是,拆成n/2,n/4,n/4。(lcm为n/2)

       AC代码如下:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#define MAXN 100005 
using namespace std;
typedef long long ll;
int t,n,k;
int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&k);
        if(n==3)
            printf("1 1 1\n");
        else if(n==4)
            printf("1 1 2\n");
        else if(n%4)
            printf("%d %d %d\n",(n+1)/2-1,(n+1)/2-1,n&1?1:2);
        else
            printf("%d %d %d\n",n/4,n/4,n/2);
    }
    return 0;
}

C2. k-LCM (hard version)

本题与C1相同,但是3<=k<=n;

由上题的结论,我们可以令(n)4=(n-1)3+1.

即先加上k-3个1,这样剩下还有3个数,令n-(k-3)。那个这个n就用C1的结论就好了。

AC代码如下:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#define MAXN 100005 
using namespace std;
typedef long long ll;
int t,n,k;
ll gcd(ll a,ll b){ return b==0?a:gcd(b,a%b); }
ll lcm(ll a,ll b){ return a*b/gcd(a,b);}
void solve(int n){
        if(n==3)
            printf("1 1 1 ");
        else if(n==4)
            printf("1 1 2 ");
        else if(n%4)
            printf("%d %d %d ",(n+1)/2-1,(n+1)/2-1,n&1?1:2);
        else
            printf("%d %d %d ",n/4,n/4,n/2);
}
int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&k);
        k-=3;
        solve(n-k);
        for(int i=0;i<k;i++)
            printf("1 ");
        printf("\n");
    }
    return 0;
}

 

posted @ 2021-03-25 21:30  mikku  阅读(36)  评论(0)    收藏  举报