ABC 227 H - Eat Them All 题解

ABC 227 H - Eat Them All 题解

讲一下我比赛的时候的思路:

首先可以有一个主要思想,就是先分配边,然后跑欧拉回路。

但是难点就在如何分配边上。

我的做法是发现有12种边,9个限制。

然后可以根据这9个限制,可以列出9个12元一次方程组。

但是至少有一个方程可以被之前的方程线性组合。

所以至少会有4个自由元。

实际上只需要枚举这4分自由元的取值,然后判定其余的是否在\([0,200]\)之间就可以了。

直接做是\(O(200^4n)\)。但是可以在枚举自由元的时候多加点特判,及时break。就可以在1.4s内通过了。

code:

/**
 *    author:  gary
 *    created: 13.11.2021 20:42:07
**/
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define rep(a,b) for(int a=0;a<b;++a)
#define LL long long
#define PB push_back
#define POB pop_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
#define A 0
#define B 1
#define C 2
#define D 3
#define E 4
#define F 5
#define G 6
#define H 7
#define I 8
#define J 9
#define K 10
#define L 11
int mat[9][13];
int deg[3][3];
const int MOD=998244353;
void add(int &X,int Y){
    X+=Y;
    if(X>=MOD) X-=MOD;
}
void sub(int &X,int Y){
    X+=MOD-Y;
    if(X>=MOD) X-=MOD;
}
int quick(int k1,int k2){
    int k3=1;for(;k2;k2>>=1,k1=1LL*k1*k1%MOD)if(k2&1)k3=1LL*k3*k1%MOD;return k3;
}
int inv(int X){return quick(X,MOD-2);}
vector<int> canchoose={B,A,E,I,J,K,C,F};// D G L H
void puzzle(){
    rep(i_,8){
        int i=canchoose[i_];
        int z=-1;
        rb(j,i_,7){
            if(mat[j][i]){
                z=j;
                break;
            }
        }
        if(z==-1){
            cout<<i_<<endl;
        }
        assert(z!=-1);
        swap(mat[z],mat[i_]);
        int iv=inv(mat[i_][i]);
        rep(j,13) mat[i_][j]=1ll*mat[i_][j]*iv%MOD;
        rep(k,8){
            if(k!=i_&&mat[k][i]){
                int v=mat[k][i];
                rep(j,13){
                    sub(mat[k][j],1ll*mat[i_][j]*v%MOD);
                }
            }
        }
    }
}
mp edg[12]={
{0,1},
{1,2},
{0,3},
{1,4},
{2,5},
{3,4},
{4,5},
{3,6},
{4,7},
{5,8},
{6,7},
{7,8}
};
mp id[9]={{0,0},{0,1},{0,2},{1,0},{1,1},{1,2},{2,0},{2,1},{2,2}};
int cnt=0;
const int MAXN=2e5+233;
int arc[MAXN];
int era[MAXN];
struct EDGE{
	int to,id;
};
vector<EDGE> g[MAXN];
vector<int> ret;
void dfs(int now){
	for(int & i=arc[now];i<g[now].size();){
		if(era[abs(g[now][i].id)]){
			++i;
			continue;
		}
		era[abs(g[now][i].id)]=true;
        ++i;
		dfs(g[now][i-1].to);
	}
    ret.PB(now);
}
char getdir(mp from,mp to){
    if(from.FIR==to.FIR&&from.SEC==to.SEC-1) return 'R';
    if(from.FIR==to.FIR&&from.SEC==to.SEC+1) return 'L';
    if(from.SEC==to.SEC&&from.FIR==to.FIR-1) return 'D';
    if(from.SEC==to.SEC&&from.FIR==to.FIR+1) return 'U';
    return '*';
}
int fa[9];
int root(int x){
    return fa[x]=(fa[x]==x? x:root(fa[x]));
}
int main(){
    int _____=0;
    rep(i,3) rep(j,3) cin>>deg[i][j],deg[i][j]*=2,_____+=deg[i][j]/2;
    mat[0][A]=mat[0][C]=1;mat[0][12]=deg[0][0];
    mat[1][A]=mat[1][D]=mat[1][B]=1;mat[1][12]=deg[0][1];
    mat[2][B]=mat[2][E]=1;mat[2][12]=deg[0][2];
    mat[3][C]=mat[3][F]=mat[3][H]=1;mat[3][12]=deg[1][0];
    mat[4][D]=mat[4][F]=mat[4][G]=mat[4][I]=1;mat[4][12]=deg[1][1];
    mat[5][G]=mat[5][E]=mat[5][J]=1;mat[5][12]=deg[1][2];
    mat[6][H]=mat[6][K]=1;mat[6][12]=deg[2][0];
    mat[7][I]=mat[7][K]=mat[7][L]=1;mat[7][12]=deg[2][1];
    mat[8][J]=mat[8][L]=1;mat[8][12]=deg[2][2];
    puzzle();
    // rep(i,9){
    //     rep(j,12){
    //         if(j==D||j==G||j==H||j==L){
    //             cout<<mat[i][j]<<' ';
    //         }
    //     }
    //     cout<<mat[i][12];
    //     cout<<endl;
    // }
    rb(g_,0,200)
    rb(l_,0,200){
        int val=mat[0][12];
        add(val,g_);
        sub(val,l_);
        if(val>200) continue;
        val=mat[2][12];
        sub(val,g_);
        add(val,l_);
        if(val>200) continue;
        val=mat[4][12];
        sub(val,l_);
        if(val>200) continue;
        val=mat[8][12];
        sub(val,l_);
        if(val>200) continue;
        rb(d_,0,200){
            int val=mat[1][12];
            sub(val,d_);
            sub(val,g_);
            add(val,l_);
            if(val>200) continue;
            val=mat[6][12];
            add(val,d_);
            add(val,g_);
            sub(val,l_);
            if(val<=200)
            rb(h_,0,200){
                if((1ll*mat[3][12]+h_+MOD-l_)%MOD>200) continue;
                int val[12];
                val[D]=d_;
                val[G]=g_;
                val[L]=l_;
                val[H]=h_;
                // if(val[D]==0&&val[G]==0&&val[H]==1&&val[L]==1);
                // else continue;
                bool bad=0;
                rep(_,8){
                    int __=canchoose[_];
                    val[__]=mat[_][12];
                    rb(z,0,11){
                        if(z==D||z==G||z==L||z==H)
                        sub(val[__],1ll*mat[_][z]*val[z]%MOD);
                    }
                    if(val[__]>200){
                        bad=1;
                        break;
                    }
                }
                if(bad){
                    continue;
                }
                else{
                    rep(i,9) fa[i]=i;
                    rep(i,12){
                        int u,v;
                        tie(u,v)=edg[i];
                        // cout<<u<<' '<<v<<' '<<' '<<val[i]<<endl;
                        if(val[i])
                        fa[root(u)]=root(v);
                    }
                    // cout<<endl;
                    bool bad=0;
                    rep(i,9){
                        if(deg[id[i].FIR][id[i].SEC]&&root(i)!=root(0))
                        {
                            // cout<<i<<" "<<deg[1][1]<<endl;
                            bad=1;
                            break;
                        }
                    }
                    if(bad){
                        continue;
                    }
                    rep(i,12){
                        int u,v;
                        tie(u,v)=edg[i];
                        rb(z,1,val[i]){
                            ++cnt;
                            g[u].PB(EDGE{v,cnt});
                            g[v].PB(EDGE{u,cnt});
                        }
                    }
                    ret.clear();
                    dfs(0);
                    reverse(ALL(ret));
                    string answer;
                    rep(i,ret.size()){
                        if(i){
                            answer.PB(getdir(id[ret[i-1]],id[ret[i]]));
                        }
                    }
                    cout<<answer<<endl;
                    return 0;
                }
            }
        }
    }
    puts("NO");
    return 0;
}
posted @ 2021-11-13 23:11  WWW~~~  阅读(337)  评论(0)    收藏  举报