제출 #978220

#제출 시각아이디문제언어결과실행 시간메모리
978220model_codeTricolor Lights (JOI24_tricolor)C++17
100 / 100
123 ms8288 KiB
//L=28

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef __int128 lll;
using ull = unsigned long long;
typedef pair<ll,ll> pll;
typedef vector<ll> vll;
typedef vector<pll> vpll;

#define mp make_pair
#define pb push_back
#define eb emplace_back
#define fi first
#define se second
#define all(x) x.begin(),x.end()
#define si(x) ll(x.size())
#define rep(i,n) for(ll i=0;i<n;i++)
#define per(i,n) for(ll i=n-1;i>=0;i--)
#define rng(i,l,r) for(ll i=l;i<r;i++)
#define gnr(i,l,r) for(ll i=r-1;i>=l;i--)
#define fore(i, a) for(auto &&i : a)
#define fore2(a, b, v) for(auto &&[a, b] : v)
#define fore3(a, b, c, v) for(auto &&[a, b, c] : v)

#include "Anna.h"

namespace{

vector<int> de_Bruijn(int typ){
	//ternaries of 3 digits
	//except numbers whose digits are all (1 or 2) (ex. 121)

	//also exept

	//typ=0: 
	//typ=1: 010,101
	//typ=2: 000,010,101
	//typ=3: 010,101,020,202

	ll len=3;
	//make graph
	ll n=pow(3,len-1);
	vector<vector<pair<ll,ll> > >g(n);
	auto valid=[&](ll x){
		//valid as an edge?
		if(typ>=1&&x==3)return 0;
		if(typ>=1&&x==9+1)return 0;
		if(typ==2&&x==0)return 0;
		if(typ==3&&x==2*3)return 0;
		if(typ==3&&x==2*9+2*1)return 0;
		rep(_,len){
			if(x%3==0)return 1;
			x/=3;
		}
		return 0;
	};
	rep(i,3*n)if(valid(i)){
		ll x=i/3;
		ll y=i%n;
		g[x].eb(y,i%3);
	}

	// {
	// 	vector<int> cnt(n,0);
	// 	rep(i,n)rep(j,si(g[i]))cnt[g[i][j].first]++;
	// 	rep(i,n)if(cnt[i]!=si(g[i])){
	// 		cout<<"invalid graph: degree sum is not 0"<<endl;
	// 	}
	// }

	//generate sequence (get an euler cycle of the graph)
	vector<int> ans;
	function<void(ll,ll)> dfs=[&](ll x,ll col){
		while(si(g[x])){
			auto [nxt,ncol]=g[x].back();
			g[x].pop_back();
			dfs(nxt,ncol);
		}
		ans.pb(col);
	};
	ll start_vertex=0;
	dfs(start_vertex,-1);
	ans.pop_back();
	reverse(all(ans));
	return ans;
}

}

pair<string,int> anna(int N,string S){
	string str="RGB";
	int B=9,L=28;
	const int TYP=4; 
	string T;
	rep(i,N+B)T+='#';
	ll id=0;

	//make 4 de_Bruijn-like sequences of period 19, 17, 16, 15
	//they make a de_Bruijn-like sequence of period LCM(19,17,16,15)
	vector<int> seq[TYP];
	rep(typ,TYP)seq[typ]=de_Bruijn(typ);

	rep(i,N/B+1){
		//repeat blocks 
		//control differnce of adjacent digits mod 3
		//a block is: (?) * ? * ? * ? * (1 or 2)
		//	?: over control
		//	*: fully under control (either 0,1,2)
		rep(typ,TYP){
			//write de Bruijn_like sequences at *s
			rep(x,3)if(str[x]!=S[id]){
				rep(y,3)if(str[y]!=S[id+1]){
					if((x-y+3)%3==seq[typ][i%si(seq[typ])]){
						T[id++]=str[x];
						T[id++]=str[y];
						x=y=3;
					}
				}
			}
		}
		rep(x,3)if(str[x]!=S[id]&&str[x]!=T[id-1]){
			T[id++]=str[x];
			break;
		}
	}
	while(si(T)>N)T.pop_back();
	if(L>N)L=N;
	return {T,L};
}
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef __int128 lll;
using ull = unsigned long long;
typedef pair<ll,ll> pll;
typedef vector<ll> vll;
typedef vector<pll> vpll;

#define mp make_pair
#define pb push_back
#define eb emplace_back
#define fi first
#define se second
#define all(x) x.begin(),x.end()
#define si(x) ll(x.size())
#define rep(i,n) for(ll i=0;i<n;i++)
#define per(i,n) for(ll i=n-1;i>=0;i--)
#define rng(i,l,r) for(ll i=l;i<r;i++)
#define gnr(i,l,r) for(ll i=r-1;i>=l;i--)
#define fore(i, a) for(auto &&i : a)
#define fore2(a, b, v) for(auto &&[a, b] : v)
#define fore3(a, b, c, v) for(auto &&[a, b, c] : v)
#include "Bruno.h"

namespace{
	int N,L;
	const int B=9,TYP=4;

//same as Anna
vector<int> de_Bruijn(int typ){
	//ternaries of 3 digits
	//except numbers whose digits are all (1 or 2) (ex. 121)

	//also exept

	//typ=0: 
	//typ=1: 010,101
	//typ=2: 000,010,101
	//typ=3: 010,101,020,202

	ll len=3;
	//make graph
	ll n=pow(3,len-1);
	vector<vector<pair<ll,ll> > >g(n);
	auto valid=[&](ll x){
		//valid as an edge?
		if(typ>=1&&x==3)return 0;
		if(typ>=1&&x==9+1)return 0;
		if(typ==2&&x==0)return 0;
		if(typ==3&&x==2*3)return 0;
		if(typ==3&&x==2*9+2*1)return 0;
		rep(_,len){
			if(x%3==0)return 1;
			x/=3;
		}
		return 0;
	};
	rep(i,3*n)if(valid(i)){
		ll x=i/3;
		ll y=i%n;
		g[x].eb(y,i%3);
	}

	// {
	// 	vector<int> cnt(n,0);
	// 	rep(i,n)rep(j,si(g[i]))cnt[g[i][j].first]++;
	// 	rep(i,n)if(cnt[i]!=si(g[i])){
	// 		cout<<"invalid graph: degree sum is not 0"<<endl;
	// 	}
	// }

	//generate sequence (get an euler cycle of the graph)
	vector<int> ans;
	function<void(ll,ll)> dfs=[&](ll x,ll col){
		while(si(g[x])){
			auto [nxt,ncol]=g[x].back();
			g[x].pop_back();
			dfs(nxt,ncol);
		}
		ans.pb(col);
	};
	ll start_vertex=0;
	dfs(start_vertex,-1);
	ans.pop_back();
	reverse(all(ans));
	return ans;
}

vector<int> seq[TYP];
map<ll,ll> rv[TYP];
map<tuple<ll,ll,ll,ll>,ll> block_id;

}

void init(int n,int l){
	N=n,L=l;
	//pre-calculate the difference sequence Anna generates
	ll bruijn_len=3;
	rep(typ,TYP){
		seq[typ]=de_Bruijn(typ);
		ll x=0;
		rep(i,si(seq[typ])+bruijn_len-1){
			x%=(ll)pow(3,bruijn_len-1);
			x=x*3+seq[typ][i%si(seq[typ])];
			if(i-(bruijn_len-1)>=0){
				rv[typ][x]=i-(bruijn_len-1);
			}
		}
	}
	rep(i,N/B+1){
		block_id[make_tuple(i%si(seq[0]),i%si(seq[1]),i%si(seq[2]),i%si(seq[3]))]=i;
	}
}

int bruno(string U){
	string str="RGB";
	if(N==L)return 1;

	//calculate difference sequence
	vll v;
	rep(i,L-1){
		rep(x,3)if(str[x]==U[i]){
			rep(y,3)if(str[y]==U[i+1]){
				v.pb((x-y+3)%3);
			}
		}
	}

	int s; // s...where a block starts at
	{
		//for each remainder mod B(block size), see whether 0s exist in the given defference sequence (length L-1).
		//It can be "No" for only 0,2,4,6,8th places (cf. a block is: ? * ? * ? * ? * (1 or 2) )
		//always "Yes" for 1,3,5,7th places, since we generated de_Bruijn-like sequences in that way
		//always "No" for 8th place.
		//we can determine which is the 8th place, seeing the distance parities of "No" places.
		vector<int> exzero(B,0);
		rep(i,si(v)){
			exzero[i%B]|=v[i]==0;
		}
		vll nonzeros;
		rep(i,B)if(!exzero[i])nonzeros.pb(i);
		if(si(nonzeros)==1){
			s=nonzeros[0];
		}
		else{
			s=nonzeros.back();
			rep(i,si(nonzeros)-1){
				if((nonzeros[i+1]-nonzeros[i])%2==1){
					s=nonzeros[i];
					break;
				}
			}
		}
	}

	//calculate block's place using pre-calculated dictionary (patterns -> number)
	vll pos;
	rep(typ,TYP){
		ll x=0;
		rep(i,si(v))if(i%B==(s+2+2*typ)%B){
			x=x*3+v[i];
		}
		ll pos_=rv[typ][x];
		if(s+2+2*typ-B<0)pos_=(pos_-1+si(seq[typ]))%si(seq[typ]);
		pos.pb(pos_);
	}
	ll res=block_id[make_tuple(pos[0],pos[1],pos[2],pos[3])];
	return res*B+B-2-s+1;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...