CF Round #569 Div2(contest1180)

比賽連接:http://codeforces.com/contest/1180c++

Problem A

題意:給出n,問方塊數。看圖理解。。。git

avatar

Solution:

找一找規律就能夠了,發現方塊數爲2n*(n-1)+1spa

Code:

#include<bits/stdc++.h>
using namespace std;
int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    return x*f;
}
int main(){
    int n=read();
    printf("%d\n",2*n*n-2*n+1);
    return 0;
}

Problem B

題意:給你一個序列,你能夠把其中任意個元素變成它的相反數-1,即:\(a_i:-a_i-1\),求乘積最大的方案code

Solution:

顯然對儘量多的非負數執行這個操做是最優的,同時咱們必然能使這個最大乘積爲非負數blog

同時對於兩個非負數\(a,b(b>a)\)來講,\((a+1)b>a(b+1)\)get

因此咱們就只須要將序列中最小的負數執行操做後的值與最大的非負數比較大小就好了it

Code:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+1;
int n,_minus,add,a[N];
int maxm,maxa=-1,idm,ida;
int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    return x*f;
}
int main(){
    n=read();
    for(int i=1;i<=n;i++){
        a[i]=read();
        a[i]>=0?++add:++_minus;
        if(a[i]>=0&&a[i]>maxa) ida=i,maxa=a[i];
        if(a[i]<0&&a[i]<maxm) idm=i,maxm=a[i];
    }int f1=_minus%2,f2=add%2;
    if(f1==f2){
        for(int i=1;i<=n;i++)
            printf("%d ",a[i]<0?a[i]:-a[i]-1);
        return 0;
    }
    if(_minus==1&&!add){
        printf("%d ",-a[1]-1);
        return 0;
    }
    if(f1!=f2){
        int id,flag=0;
        if(-maxm-1>maxa) id=idm;
        else id=ida,flag=1;
        for(int i=1;i<id;i++)
            printf("%d ",a[i]<0?a[i]:-a[i]-1);
        printf("%d ",flag?a[id]:-a[id]-1);
        for(int i=id+1;i<=n;i++)
            printf("%d ",a[i]<0?a[i]:-a[i]-1);      
    }
}

Problem C

題意:給你一個序列,每次操做取出序列前兩個元素\(a,b\),將較大元素放在序列首位,較小元素放在序列末尾,有m次詢問,每次詢問你第x次操做取出的是哪兩個元素io

Solution:

顯然,當序列中的最大元素爲首位時,全部跟它比較的元素都會被踢到隊尾,造成循環,而最大元素替換到隊首最多須要n-1次操做,則咱們能夠模擬最大元素替換到隊首以前的全部操做,以後的操做則能夠根據循環O(1)算出class

Code:

#include<bits/stdc++.h>
#define ll long long 
#define mp make_pair
#define fir first
#define sec second
using namespace std;
const int N=1e5+1;
int n,m,maxn;
int head,cnt,tail,q[N*31];
pair<int,int> u[N];
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    return x*f;
}
int main(){
    n=read(),m=read();
    for(int i=1;i<=n;i++){
        q[++tail]=read();
        if(q[i]>maxn) maxn=q[i];
    }head=1;
    while(1){
        int x=q[head],y=q[head+1];
        u[++cnt]=mp(x,y);
        if(x==maxn) break;
        if(x>y) q[head+1]=q[head++],q[++tail]=y;
        else ++head,q[++tail]=x;
    }
    for(int i=1;i<=m;i++){
        ll x=read();
        if(x<=cnt) printf("%d %d\n",u[x].fir,u[x].sec);
        else printf("%d %d\n",maxn,q[head+1+(x-cnt)%(n-1)]);
    }
    return 0;
}

Problem D

題意:給定一個n*m的矩陣,一開始你在(1,1);每次移動時,設你所在點爲(x,y),你可選取任意二元組(dx,dy),移動到(x+dx,y+dy)點上,但每次選取的二元組(dx,dy)不能爲以前用過的。如今問是否有一種方案使你恰好通過每一個點一次,若是有,按前後順序輸出到達的點,不然輸出-1。test

Solution:

這是一道構造題。考慮從(1,1)和(n,m)兩個點依次反向之字形往返跳躍,正確性易證,詳見代碼(由於不是很好描述)

Code:

#include<bits/stdc++.h>
#define mp make_pair
using namespace std;
const int N=1e6+1;
int n,m,add1=1,add2=-1;
int nx,ny,mx,my,flag;
int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
    return x*f;
}
void ins(int opt){
    if(!opt){
        printf("%d %d\n",nx,ny);
        if(nx+add1>n||nx+add1<1) ++ny,add1=-add1;
        else nx+=add1;
    }else{
        printf("%d %d\n",mx,my);
        if(mx+add2<1||mx+add2>n) --my,add2=-add2;
        else mx+=add2;
    }
}
int main(){
    n=read(),m=read();
    nx=ny=1,mx=n,my=m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            ins(flag),flag^=1;
    return 0;
}
相關文章
相關標籤/搜索