Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma GCC optimize ("O3")
- #pragma GCC target ("sse4")
- #include <bits/stdc++.h>
- #include <ext/pb_ds/assoc_container.hpp>
- #include <ext/pb_ds/tree_policy.hpp>
- using namespace std;
- template <class T>
- using ordered_set = __gnu_pbds::tree<T, __gnu_pbds::null_type, less<T>, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update>;
- template <class T>
- using ordered_multiset = __gnu_pbds::tree<T, __gnu_pbds::null_type, less_equal<T>, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update>;
- #define PI atan2(0, -1)
- #define epsilon 1e-9
- #define INF 5e18
- #define MOD 1000000007
- #define mp make_pair
- #define pb push_back
- #define f first
- #define s second
- #define lb lower_bound
- #define ub upper_bound
- int kase, N;
- // Priority Queue State: ( ( Number of 1 Bits , Number of Total Bits ) , ( Current Residue , Previous Residue ) )
- priority_queue<pair<pair<int, int>, pair<int, int>>, vector<pair<pair<int, int>, pair<int, int>>>,
- greater<pair<pair<int, int>, pair<int, int>>>> pq;
- pair<int, int> dist [100010];
- vector<int> forAdj [100010], backAdj [100010];
- bool backReachable [100010];
- int main(){
- //freopen("sort.in", "r", stdin); freopen("sort.out", "w", stdout);
- ios_base::sync_with_stdio(0); cin.tie(0); cout << fixed << setprecision(10);
- cin >> kase;
- for(int kk = 1; kk <= kase; kk++){
- cin >> N;
- // Edge case where N = 1
- if(N == 1){
- cout << "0\n";
- continue;
- }
- // Do the Dijkstra and Make the DAGs
- for(int i = 0; i < N; i++){
- dist[i] = {MOD, MOD};
- forAdj[i] = vector<int>(); backAdj[i] = vector<int>();
- backReachable[i] = false;
- }
- pq = priority_queue<pair<pair<int, int>, pair<int, int>>, vector<pair<pair<int, int>, pair<int, int>>>,
- greater<pair<pair<int, int>, pair<int, int>>>>();
- pq.push({{1, 0}, {1, 1}});
- while(pq.size() > 0){
- pair<pair<int, int>, pair<int, int>> state = pq.top(); pq.pop();
- int curr = state.s.f, par = state.s.s;
- if(dist[curr] < state.f) continue;
- forAdj[par].pb(curr);
- backAdj[curr].pb(par);
- if(dist[curr] == state.f) continue;
- else{
- dist[curr] = state.f;
- assert(backAdj[curr].size() == 1);
- }
- if(dist[(2*curr)%N] > mp(state.f.f, state.f.s+1)) pq.push({{state.f.f, state.f.s+1} ,{(2*curr)%N, curr}});
- if(dist[(2*curr+1)%N] > mp(state.f.f+1, state.f.s+1)) pq.push({{state.f.f+1, state.f.s+1}, {(2*curr+1)%N, curr}});
- }
- // Check if a path that leads to 0 exists from every node in the forward adjacency graph
- queue<int> q; backReachable[0] = true; q.push(0);
- while(q.size() > 0){
- int curr = q.front(); q.pop();
- for(int nexty : backAdj[curr])
- if(!backReachable[nexty]){
- backReachable[nexty] = true;
- q.push(nexty);
- }
- }
- // Greedily reconstruct the best solution
- vector<int> ret; ret.pb(dist[0].s);
- for(int bitPos = dist[0].s-1, curr = 1; bitPos > -1; bitPos--){
- if(find(forAdj[curr].begin(), forAdj[curr].end(), (curr*2)%N) != forAdj[curr].end() && backReachable[(curr*2)%N]){
- curr = (curr*2)%N;
- }
- else{
- curr = (curr*2+1)%N;
- ret.pb(bitPos);
- }
- }
- for(int i = ret.size()-1; i > -1; i--) cout << ret[i] << (i ? ' ' : '\n');
- }
- return 0;
- }
- /******************************
- Kateba ii dake no hanashi darou
- Success is only a victory away
- - No Game No Life Opening
- ******************************/
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement