1. 程式人生 > >記第一場atcoder和codeforces 2018-2019 ICPC, NEERC, Northern Eurasia Finals Online Mirror

記第一場atcoder和codeforces 2018-2019 ICPC, NEERC, Northern Eurasia Finals Online Mirror

下午連著兩場比賽,爽。

首先是codeforses,我和一位dalao一起打的,結果考炸了,幸虧不計rating。。


A Alice the Fan

這個就是記憶化搜尋一下預處理,然後直接回答詢問好了,我肯定是傻逼了,還寫了這麼長,幸虧調處來了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;

typedef long long ll;
const int Maxn=210;

int vis[10][Maxn][Maxn],xi[10][Maxn][Maxn],xj[10][Maxn][Maxn];

void ycl() {
    for(int i=25;i<=200;i++)
        for(int j=0;j<=200;j++) {
            if(j>i) continue;
            if(i==25&&j<24) vis[1][i][j]=1;
            else if(i>25&&j==i-2) vis[1][i][j]=1;
        }
    for(int i=50;i<=200;i++)
        for(int j=0;j<=200;j++) {
            for(int k=0;k<=j&&k<24;k++)
                if(vis[1][i-25][j-k]) {
                    vis[2][i][j]=1;
                    xi[2][i][j]=25;
                    xj[2][i][j]=k;
                    break;
                }
            if(vis[2][i][j]) continue;
            for(int k=26;k<=i&&k<=j+2;k++)
                if(vis[1][i-k][j-k+2]) {
                    vis[2][i][j]=1;
                    xi[2][i][j]=k;
                    xj[2][i][j]=k-2;
                    break;
                }
        }
    for(int i=65;i<=200;i++)
        for(int j=0;j<=200;j++) {
            for(int k=0;k<=j&&k<14;k++)
                if(vis[2][i-15][j-k]) {
                    vis[3][i][j]=1;
                    xi[3][i][j]=15;
                    xj[3][i][j]=k;
                    break;
                }
            if(vis[3][i][j]) continue;
            for(int k=16;k<=i&&k<=j+2;k++)
                if(vis[2][i-k][j-k+2]) {
                    vis[3][i][j]=1;
                    xi[3][i][j]=k;
                    xj[3][i][j]=k-2;
                    break;
                }
        }
    for(int i=65;i<=200;i++)
        for(int j=25;j<=200;j++) {
            for(int k=0;k<24;k++)
                if(vis[3][i-k][j-25]) {
                    vis[4][i][j]=1;
                    xi[4][i][j]=k;
                    xj[4][i][j]=25;
                    break;
                }
            if(vis[4][i][j]) continue;
            for(int k=26;k<=i+2&&k<=j;k++)
                if(vis[3][i-k+2][j-k]) {
                    vis[4][i][j]=1;
                    xi[4][i][j]=k-2;
                    xj[4][i][j]=k;
                    break;
                }
        }
    for(int i=65;i<=200;i++)
        for(int j=50;j<=200;j++) {
            for(int k=0;k<24;k++)
                if(vis[4][i-k][j-25]) {
                    vis[5][i][j]=1;
                    xi[5][i][j]=k;
                    xj[5][i][j]=25;
                    break;
                }
            if(vis[5][i][j]) continue;
            for(int k=26;k<=i+2&&k<=j;k++)
                if(vis[4][i-k+2][j-k]) {
                    vis[5][i][j]=1;
                    xi[5][i][j]=k-2;
                    xj[5][i][j]=k;
                    break;
                }
        }
    for(int i=75;i<=200;i++)
        for(int j=0;j<=200;j++) {
            for(int k=0;k<=j&&k<24;k++)
                if(vis[2][i-25][j-k]) {
                    vis[6][i][j]=1;
                    xi[6][i][j]=25;
                    xj[6][i][j]=k;
                    break;
                }
            if(vis[6][i][j]) continue;
            for(int k=26;k<=i&&k<=j+2;k++)
                if(vis[2][i-k][j-k+2]) {
                    vis[6][i][j]=1;
                    xi[6][i][j]=k;
                    xj[6][i][j]=k-2;
                    break;
                }
        }
    for(int i=75;i<=200;i++)
        for(int j=25;j<=200;j++) {
            for(int k=0;k<24;k++)
                if(vis[6][i-k][j-25]) {
                    vis[7][i][j]=1;
                    xi[7][i][j]=k;
                    xj[7][i][j]=25;
                    break;
                }
            if(vis[7][i][j]) continue;
            for(int k=26;k<=i+2&&k<=j;k++)
                if(vis[6][i-k+2][j-k]) {
                    vis[7][i][j]=1;
                    xi[7][i][j]=k-2;
                    xj[7][i][j]=k;
                    break;
                }
        }
}

int main() {
//  freopen("test.in","r",stdin);
    int t,x,y;
    scanf("%d",&t);
    ycl();
    while(t--) {
        scanf("%d%d",&x,&y);
        if(!(vis[6][x][y]||vis[7][x][y]||vis[5][x][y]||vis[6][y][x]||vis[7][y][x]||vis[5][y][x])) {
            puts("Impossible");
            continue;
        }
        if(vis[6][x][y]) {
            puts("3:0");
            int tx=xi[6][x][y],ty=xj[6][x][y];
            printf("%d:%d ",tx,ty);
            x-=tx,y-=ty;
            tx=xi[2][x][y],ty=xj[2][x][y];
            printf("%d:%d ",tx,ty);
            x-=tx,y-=ty;
            printf("%d:%d\n",x,y);
            continue;
        }
        if(vis[7][x][y]) {
            puts("3:1");
            int tx=xi[7][x][y],ty=xj[7][x][y];
            printf("%d:%d ",tx,ty);
            x-=tx,y-=ty;
            tx=xi[6][x][y],ty=xj[6][x][y];
            printf("%d:%d ",tx,ty);
            x-=tx,y-=ty;
            tx=xi[2][x][y],ty=xj[2][x][y];
            printf("%d:%d ",tx,ty);
            x-=tx,y-=ty;
            printf("%d:%d\n",x,y);
            continue;
        }
        if(vis[5][x][y]) {
            puts("3:2");
            int tx=xi[5][x][y],ty=xj[5][x][y];
            printf("%d:%d ",tx,ty);
            x-=tx,y-=ty;
            tx=xi[4][x][y],ty=xj[4][x][y];
            printf("%d:%d ",tx,ty);
            x-=tx,y-=ty;
            int ttx=xi[3][x][y],tty=xj[3][x][y];
            x-=ttx,y-=tty;
            tx=xi[2][x][y],ty=xj[2][x][y];
            printf("%d:%d ",tx,ty);
            x-=tx,y-=ty;
            printf("%d:%d ",x,y);
            printf("%d:%d\n",ttx,tty);
            continue;
        }
        if(vis[5][y][x]) {
            puts("2:3");
            swap(x,y);
            int tx=xi[5][x][y],ty=xj[5][x][y];
            printf("%d:%d ",ty,tx);
            x-=tx,y-=ty;
            tx=xi[4][x][y],ty=xj[4][x][y];
            printf("%d:%d ",ty,tx);
            x-=tx,y-=ty;
            int ttx=xi[3][x][y],tty=xj[3][x][y];
            x-=ttx,y-=tty;
            tx=xi[2][x][y],ty=xj[2][x][y];
            printf("%d:%d ",ty,tx);
            x-=tx,y-=ty;
            printf("%d:%d ",y,x);
            printf("%d:%d\n",tty,ttx);
            continue;
        }
        if(vis[7][y][x]) {
            puts("1:3");
            swap(x,y);
            int tx=xi[7][x][y],ty=xj[7][x][y];
            printf("%d:%d ",ty,tx);
            x-=tx,y-=ty;
            tx=xi[6][x][y],ty=xj[6][x][y];
            printf("%d:%d ",ty,tx);
            x-=tx,y-=ty;
            tx=xi[2][x][y],ty=xj[2][x][y];
            printf("%d:%d ",ty,tx);
            x-=tx,y-=ty;
            printf("%d:%d\n",y,x);
            continue;
        }
        if(vis[6][y][x]) {
            puts("0:3");
            swap(x,y);
            int tx=xi[6][x][y],ty=xj[6][x][y];
            printf("%d:%d ",ty,tx);
            x-=tx,y-=ty;
            tx=xi[2][x][y],ty=xj[2][x][y];
            printf("%d:%d ",ty,tx);
            x-=tx,y-=ty;
            printf("%d:%d\n",y,x);
            continue;
        }
    }
    return 0;
}

E Easy Chess

這道題我的構造方法就是對於63步直接打個表,否則的話就讓他一步一步走,從第一層到第六層走,如果這時剩餘的步數為2,那麼直接向上再向右,直接到達終點。

然後就到了a7,然後走法就是上右下右迴圈,還是如果剩餘步數為2,直接到終點就好了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;

typedef long long ll;
const int Maxn=110000;

int main() {
//  freopen("test.in","r",stdin);
    int n;
    scanf("%d",&n);
    if(n==63) puts("a1 b1 c1 d1 e1 f1 g1 h1 h2 g2 f2 e2 d2 c2 b2 a2 a3 b3 c3 d3 e3 f3 g3 h3 h4 g4 f4 e4 d4 c4 b4 a4 a5 b5 c5 d5 e5 f5 g5 h5 h6 g6 f6 e6 d6 c6 b6 a6 a7 a8 b8 b7 c7 c8 d8 d7 e7 e8 f8 f7 h7 g7 g8 h8");
    else {
        printf("a1 ");
        int x=1,y=1;
        while(n!=2) {
            n--;
            if(x&1)
                if(y==8) x++;
                else y++;
            else
                if(y==1) x++;
                else y--;
            printf("%c%d ",y+'a'-1,x);
            if(x==7) break;
        }
        if(n==2) {
            if(y==8) printf("h7 h8\n");
            else printf("%c8 h8\n",y+'a'-1);
        }
        else {
            while(n!=2) {
                n--;
                if(y&1)
                    if(x==7) x++;
                    else y++;
                else
                    if(x==8) x--;
                    else y++;
                printf("%c%d ",y+'a'-1,x);
            }
            if(x==8) printf("g8 h8\n");
            else printf("h7 h8\n");
        }
    }
    return 0;
}

F Fractions

這個題的話就是求若干的分數相加等於\(\frac{n-1}{n}\),其中分母不能等於n,分子必須是正的。

那麼原來分數是\(\frac{a_i}{b_i}\),那麼可以化成\(\frac{a_i\frac n {b_i}}{n}\),那麼我們令新的\(b_i\)等於\(\frac{n}{b_i}\),所求即為若干的\(a_i\)\(b_i\)相乘,和為n-1。

先對n分解質因數,如果質因數個數為1,那麼一定不行。

否則,設a,b分別是它的不同的質因數,可以用擴歐求出來x,y使得\(ax+by=n-1\)

那麼一定存在下面的式子:

\(a\equiv (n-1)x^{-1}(mod\ y)\)

那麼一定存在一組解使得\(0<a<y\),又\(xy\le n\),那麼\(ax<n\),因為\(ax\ne n-1\),所以\(ay<n-1\),所以\(by>0\),所以\(b>0\)

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;

typedef long long ll;
const int Maxn=110000;

void gcd(ll x,ll y,ll &a,ll &b) {
    if(y==0) {
        a=1;
        b=0;
        return;
    }
    gcd(y,x%y,b,a);
    b-=x/y*a;
}

int main() {
//  freopen("test.in","r",stdin);
    ll n,num1=0,num2=0;
    scanf("%I64d",&n);
    ll temp=n-1;
    for(ll i=2;i*i<=n;i++)
        if(n%i==0) {
            if(num1) {
                num2=i;
                break;
            }
            num1=i;
            while(n%i==0) n/=i;
        }
    if(n!=1&&num1&&!num2) num2=n;
    if(num2==0) {
        puts("NO");
        return 0;
    }
    ll a,b;
    gcd(num1,num2,a,b);
    a*=temp;b*=temp;
    if(a>0) {
        ll temp=a/num2;
        a%=num2;
        b+=num1*temp;
    }
    else {
        ll temp=b/num1;
        b%=num1;
        a+=num2*temp;
    }
    puts("YES\n2");
    printf("%I64d %I64d\n",a,(temp+1)/num1);
    printf("%I64d %I64d\n",b,(temp+1)/num2);
    return 0;
}

G Guest Student

這道題並不是我做的啊,聽說是列舉?

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,tot,t,a[10];
int work(int p){
    int m=n;
    for(int i=p;i<=7;i++){
        m-=a[i];
        if(m==0) return i-p+1;
    }
    int ans=7-p+1;
    int x=m/tot,y=m%tot;
    if(y==0) x--,y=tot;
    ans+=x*7;
    for(int i=1;i<=7;i++){
        y-=a[i];
        if(y==0) return ans+i;
    }
}
int main(){
//  freopen("1.in","r",stdin);
    scanf("%d",&t);
    while(t--){
        int ans=0x7fffffff;
        scanf("%d",&n);
        tot=0;
        for(int i=1;i<=7;i++){
            scanf("%d",&a[i]);
            tot+=a[i];
        }
        for(int i=1;i<=7;i++)
            if(a[i]==1)
                ans=min(ans,work(i));
        printf("%d\n",ans);
    }
}

L Lazyland

傻逼題,不說了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;

typedef long long ll;
const int Maxn=110000;

int n,k,x,b[Maxn];
ll ans;
priority_queue<ll,vector<ll>,greater<ll> >hi;
priority_queue<int> h[Maxn];
vector<int> vi[Maxn];

int main() {
//  freopen("test.in","r",stdin);
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++) {
        scanf("%d",&x);
        vi[x].push_back(i);
    }
    for(int i=1;i<=n;i++)
        scanf("%d",&b[i]);
    for(int i=1;i<=k;i++)
        for(int j=0;j<vi[i].size();j++)
            h[i].push(b[vi[i][j]]);
    int num=0;
    for(int i=1;i<=k;i++)
        if(h[i].empty()) num++;
        else {
            h[i].pop();
            while(!h[i].empty()) {
                hi.push(h[i].top());
                h[i].pop();
            }
        }
    while(num--) {
        ans+=hi.top();
        hi.pop();
    }
    printf("%I64d",ans);
    return 0;
}

然後是一場atcoder,這還是我第一次打atcoder啊,還是一場ABC,雖然題目這麼水,但是我還是考炸了。。

題解就算了,反正題目這麼水。。