1. 程式人生 > 實用技巧 >ICPC2017南寧站題解(A,E,F,H,I,J,L,M)

ICPC2017南寧站題解(A,E,F,H,I,J,L,M)

VP比賽時間:2020-07-23: 7 / 13 Rank: 35 / 228

VP通過:A,E,F,H,I,J,L

賽後補題:M

感想:這場對大數要求挺多(2道題F和L),我隊Java選手很給力。然後銀牌題大概是E和M(M那時候沒信心去挑戰畢竟在銀首,但是賽後補題發現是一個floyd+裸最大獨立集,還是簡單題。E是偏向思維的概率數學)。H是大模擬,I題是無腦dfs模擬。就這場和icpc2019南昌來說,我感覺銀牌圖論題可能要求並不是很高,要有信心去挑戰銀牌題吧。畢竟感覺銅牌圖論撐死就是生成樹和最短路了(真的嗎?)

A.Abiyoyo

第一簽到題,Anonytt,懶得說:

#include<bits/stdc++.h>
#define
ll long long #define rep(i,a,n) for(int i=a;i<=n;i++) #define per(i,n,a) for(int i=n;i>=a;i--) #define endl '\n' #define eps 0.000000001 #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define IO ios::sync_with_stdio(false);cin.tie(0); using namespace std; const int INF=0x3f3f3f3f; const ll inf=0x3f3f3f3f3f3f3f3f
; const int mod=1e9+7; const int maxn=1e5+5; int main(){ int T;cin>>T; while(T--){ int n;cin>>n; rep(i,1,n){ puts("Abiyoyo, Abiyoyo."); } rep(i,1,2){ puts("Abiyoyo, yo yoyo yo yoyo."); } } }
View Code

E. The Champion

銀牌題,Libm,我不會。

#include <bits/stdc++.h>
#define ll unsigned long long
#define endl '\n'
using namespace std;
double p; 
ll fa[65];
double cal(int r,ll k){
    double ans=1;
    if(r==1){
        if(k==1) ans=1;
        else ans=1-p;
    }
    else if(k<=fa[r-1]){
        double cur=1;
        while(k<=fa[r-1]){
            cur=cur*p;
            r--;
            if(r==1) break;
        }
        ans=(1-p)+p-cur+cur*cal(r,k);
    }
    else{
        while(k>fa[r-1]){
            k-=(fa[r-1]);
            r--;
            ans*=(1-p);
            if(r==1) break;
        } 
        ans*=cal(r,k);
    } 
    return ans;
}
double solve(int r,ll k){
    double ans=1;
    if(r==1){
        if(k==1) ans=p;
        else ans=1-p;
        return ans;
    }
    if(k==fa[r-1]+1){
        for(int i=1;i<r;i++) ans*=p;
        ans*=(1-p);
    }
    else if(k<fa[r-1]+1){
        for(int i=1;i<r;i++) ans*=p;
        double now=cal(r-1,k);
        ans=ans*(now*p+(1-now)*(1-p));
    }
    else{
        while(k>fa[r-1]+1){
            k-=fa[r-1];
            r--;
            ans*=(1-p);
        } 
        ans*=solve(r,k);
    }
    return ans;
}

int main(){
    ios::sync_with_stdio(false);cin.tie(0);
    int T;cin>>T;
    fa[0]=1; 
    for(int i=1;i<=63;i++) fa[i]=fa[i-1]*2;
    while(T--){
        int r; ll k;
        cin>>r>>k>>p;
        double ans=solve(r,k);
        printf("%.6lf\n",ans); 
    }
}
View Code

F. The Chosen One

簽到java大數題,kele

import java.math.BigInteger;
import java.util.Scanner;

public class Main{
    public static void main(String[] args){
        Scanner input = new Scanner(System.in);
        
        int t = input.nextInt();

        while (t > 0) {
            BigInteger m = input.nextBigInteger();
            BigInteger ans = (new BigInteger("2")).pow(m.bitLength() - 1);
            System.out.println(ans);
            t--;
        }

        input.close();
    }
}
View Code

H.The Game of Life

銅牌大模擬,我提供我(Anonytt)的寫法,因為是個無限大的圖,但是最多就321次衍生,所以實際上最終圖的大小是不會超過(2*321+n)*(2*321+m),為了方便所以我就把初始點全部行列+400。然後記錄當前是活著的點,把他們存在set裡,然後並對活著的周邊8個點的cnt進行統計。每次更新,用queue佇列來縮減時間。

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)
#define endl '\n'
#define eps 0.000000001
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define IO ios::sync_with_stdio(false);cin.tie(0);
using namespace std;
const int INF=0x3f3f3f3f;
const ll inf=0x3f3f3f3f3f3f3f3f;
const int mod=1e9+7;
const int maxn=1e5+5;
int a[900][900],cnt[900][900];
int dx[9]={1,-1,0,0,1,1,-1,-1};
int dy[9]={0,0,1,-1,1,-1,1,-1};
int n,m;
int main(){
    int T;scanf("%d",&T);
    while(T--){
        mem(a,0);mem(cnt,0);
        scanf("%d%d",&n,&m);
        int maxx=0,id=0;
        set<pair<int,int> >s;
        rep(i,1,n){
            rep(j,1,m){
                char xx;cin>>xx;
                if(xx=='#'){
                    int u=i+400,v=j+400;
                    a[u][v]=1;++maxx;
                    rep(o,0,7){
                        int x=u+dx[o],y=v+dy[o];
                        cnt[x][y]+=1;
                        s.insert({x,y});
                    }
                    s.insert({u,v});
                }
                else a[i+400][j+400]=0;
            }
        }
        int c;
        rep(t,1,321){
            int cur=0;
            queue<pair<int,int> >q;
            for(auto it:s){
                int x=it.first,y=it.second;
                if(cnt[x][y]==3&&!a[x][y]) {a[x][y]=1;++cur;q.push({x,y});}
                else if((cnt[x][y]==2&&a[x][y])||(cnt[x][y]==3&&a[x][y])) {a[x][y]=1;++cur;q.push({x,y});}
                else if((cnt[x][y]<=1&&a[x][y])||(cnt[x][y]>=4&&a[x][y])) {a[x][y]=0;}
                cnt[x][y]=0;
            }
            if(cur>maxx) {maxx=cur,id=t;}
            if(t==321) c=cur;
            s.clear();
            if(t<321){
                while(!q.empty()){
                    auto now=q.front();q.pop();
                    int x=now.first,y=now.second;
                    s.insert({x,y});
                }
                queue<pair<int,int> >que;
                for(auto it:s){
                    int xx=it.first,yy=it.second;
                    rep(o,0,7){
                        int x=xx+dx[o],y=yy+dy[o];
                        cnt[x][y]+=1;que.push({x,y});
                    }
                }
                while(!que.empty()){
                    auto now=que.front();que.pop();
                    int x=now.first,y=now.second;
                    s.insert({x,y});
                }    
            }
        }
        cout<<id<<" "<<maxx<<" "<<c<<endl;
    }
}
View Code

I.Rake It In

銅牌無腦暴力dfs。Anonytt,時間複雜度大概=200*pow(9,6)≈1e8,剛好能擦過,所以就無腦暴力吧

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)
#define endl '\n'
#define eps 0.000000001
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define IO ios::sync_with_stdio(false);cin.tie(0);
using namespace std;
const int INF=0x3f3f3f3f;
const ll inf=0x3f3f3f3f3f3f3f3f;
const int mod=1e9+7;
const int maxn=1e5+5;
int a[5][5],k;
int find(int x,int y){
    int res=0;
    res+=a[x][y]+a[x+1][y]+a[x][y+1]+a[x+1][y+1];
    return res;
}
void rot(int x,int y){
    int temp=a[x][y];
    a[x][y]=a[x][y+1];
    a[x][y+1]=a[x+1][y+1];
    a[x+1][y+1]=a[x+1][y];
    a[x+1][y]=temp;
}
void back(int x,int y){
    int temp=a[x][y];
    a[x][y]=a[x+1][y];
    a[x+1][y]=a[x+1][y+1];
    a[x+1][y+1]=a[x][y+1];
    a[x][y+1]=temp;
}
int dfs(int t){
    if(t==2*k){
        int ans=INF,x,y;
        rep(i,1,3){
            rep(j,1,3){
                ans=min(ans,find(i,j));
            }
        }
        return ans;
    }
    else{
        if(t%2==1){
            int ans=0,x,y;
            rep(i,1,3){
                rep(j,1,3){
                    rot(i,j);
                    ans=max(ans,find(i,j)+dfs(t+1));
                    back(i,j);
                }
            }
            return ans;
        }
        if(t%2==0){
            int ans=INF,x,y;
            rep(i,1,3){
                rep(j,1,3){
                    rot(i,j);
                    ans=min(ans,find(i,j)+dfs(t+1));
                    back(i,j);
                }
            }
            return ans;            
        }
    } 
}
int main(){
    int T;scanf("%d",&T);
    while(T--){
        scanf("%d",&k);
        rep(i,1,4){
            rep(j,1,4){
                scanf("%d",&a[i][j]);
            }
        }
        cout<<dfs(1)<<endl;
    }
}
View Code

J. Rearrangement

簽到,Anonytt

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)
#define endl '\n'
#define eps 0.000000001
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define IO ios::sync_with_stdio(false);cin.tie(0);
using namespace std;
const int INF=0x3f3f3f3f;
const ll inf=0x3f3f3f3f3f3f3f3f;
const int mod=1e9+7;
const int maxn=1e5+5;
int a[2*maxn];
int main(){
    int T;scanf("%d",&T);
    while(T--){
        int n;scanf("%d",&n);
        int cnt1=0,cnt2=0,cnt3=0;
        rep(i,1,2*n){
            scanf("%d",&a[i]);
            if(a[i]%3==0) cnt3++;
            if(a[i]%3==1) cnt1++;
            if(a[i]%3==2) cnt2++;
        }
        if(cnt3>n) {puts("NO");continue;}
        if(cnt3==n){puts("YES");continue;}
        else if(cnt3==0){
            if(cnt1&&cnt2) puts("NO");
            else puts("YES");
        }
        else if(cnt3==1){
            if(cnt1&&cnt2) puts("NO");
            else puts("YES");
        }
        else if(cnt3==2){
            if(cnt1%2==0&&cnt2%2==0){puts("NO");continue;}
            else puts("YES");
        }
        else puts("YES");
    }
}
View Code

L. Twice Equation

大數java+板子,kele

import java.math.BigInteger;
import java.util.Scanner;

public class Main{
    public static void main(String[] args){
        Scanner input = new Scanner(System.in);

        int t = input.nextInt();
        BigInteger[] a = new BigInteger[1000];

        a[0] = BigInteger.ZERO;
        a[1] = BigInteger.valueOf(3);

        BigInteger ke = new BigInteger("6");
        BigInteger le = new BigInteger("2");

        for(int i = 2; i <= 400; i++){
            a[i] = ((a[i - 1].multiply(ke)).subtract(a[i - 2])).add(le);
//             System.out.println(a[i]);
        }
        for(int i = 0; i < t; i++) {
            boolean flag = false;
            BigInteger L = input.nextBigInteger();
            for(int j = 0; j <= 400; j++){
                if(a[j].compareTo(L) >= 0){
                    System.out.println(a[j]);
                    flag = true;
                    break;
                }
            }
            if(!flag) System.out.println(-1);
        }

        input.close();
    }
}
View Code

M.The Maximum Unreachable Node Set

(賽後通過Anonytt),其實就是一個最大獨立集的問題,不過需要之前用floyd轉化,其實看出最大獨立集不難,關鍵是想到floyd轉化

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)
#define endl '\n'
#define eps 0.000000001
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define IO ios::sync_with_stdio(false);cin.tie(0);
using namespace std;
const int INF=0x3f3f3f3f;
const ll inf=0x3f3f3f3f3f3f3f3f;
const int mod=1e9+7;
const int maxn=1e5+5;
int n,m,line[505][505],used[505],match[505];
int find(int x){
    rep(i,1,n){
        if(!used[i]&&line[x][i]){
            used[i]=true;
            if(match[i]==0||find(match[i])){
                match[i]=x;
                return true;
            }
        }
    }
    return false;
}
int main(){
    int T;scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        mem(line,0);mem(match,0);
        rep(i,1,m){
            int u,v;scanf("%d%d",&u,&v);
            line[u][v]=1;
        }
        rep(k,1,n){
            rep(i,1,n){
                rep(j,1,n){
                    if(line[i][k]&&line[k][j]) line[i][j]=1;
                }
            }
        }
        int ans=0;
        rep(i,1,n){
            mem(used,0);
            if(find(i)) ++ans;
        }
        printf("%d\n",n-ans);
    }
}
View Code

再接再厲啊,希望現場icpc區域賽能有銀牌qwq