code in cpp
تم الإنشاء في: ١٤ مارس ٢٠٢٦
تمت الإجابة باستخدام GPT-5.4 Thinking بواسطة Chat01
تم الإنشاء في: ١٤ مارس ٢٠٢٦
تمت الإجابة باستخدام GPT-5.4 Thinking بواسطة Chat01
code in cpp
pythonfrom functools import lru_cache from math import gcd from itertools import combinations_with_replacement, product @lru_cache(None) def f(a,b,c): a,b,c = sorted((a,b,c)) if a==0: return 0 if a==1: return 1 best=10**9 # choose decrement each coord for i,(x,y,z) in enumerate([(a,b,c),(b,a,c),(c,a,b)]): d=gcd(x-1,gcd(y,z)) nx,ny,nz=(x-1)//d,y//d,z//d arr=sorted((nx,ny,nz)) best=min(best,1+f(*arr)) return best vals={} for a in range(1,11): for b in range(a,11): for c in range(b,11): vals[(a,b,c)] = f(a,b,c) list(vals.items())[:10], f(4,7,8), f(9,25,37) ([((1, 1, 1), 1), ((1, 1, 2), 1), ((1, 1, 3), 1), ((1, 1, 4), 1), ((1, 1, 5), 1), ((1, 1, 6), 1), ((1, 1, 7), 1), ((1, 1, 8), 1), ((1, 1, 9), 1), ((1, 1, 10), 1)], 3, 4)
pythonfor a in range(1,8): rows=[] for b in range(a,8): for c in range(b,8): rows.append(((a,b,c),f(a,b,c))) print("a",a, rows[:10], '...')
pythonfrom functools import lru_cache from math import gcd def normalize(t): g=0 for x in t: g=gcd(g,x) return tuple(sorted(x//g for x in t)) @lru_cache(None) def f2(a,b,c): a,b,c=sorted((a,b,c)) best=a # decrement smallest to zero directly m=max(a,b,c) for D in range(2,m+1): adj=(a-a%D,b-b%D,c-c%D) if 0 in adj: # if some become 0, terminal cost = sum remainders + maybe? Actually reaching zero itself volume zero, don't divide further. best=min(best,(a%D)+(b%D)+(c%D)) continue g=gcd(adj[0],gcd(adj[1],adj[2])) if g>1: na,nb,nc=sorted((adj[0]//g,adj[1]//g,adj[2]//g)) best=min(best,(a%D)+(b%D)+(c%D)+f2(na,nb,nc)) return best ok=True bad=[] for a in range(1,11): for b in range(a,11): for c in range(b,11): if gcd(a,gcd(b,c))!=1: continue if f(a,b,c)!=f2(a,b,c): bad.append(((a,b,c),f(a,b,c),f2(a,b,c))) ok=False if len(bad)>20: break if len(bad)>20: break if len(bad)>20: break ok, bad[:20] (False, [((7, 10, 10), 4, 3)])
pythonfrom functools import lru_cache from math import gcd import random, sys sys.setrecursionlimit(10000) seen=0 @lru_cache(None) def ff(a,b,c): global seen seen+=1 a,b,c=sorted((a,b,c)) if a==0: return 0 if a==1: return 1 best=a d=gcd(b,c) d1=gcd(a,c) d2=gcd(a,b) # one-step recursion for x,y,z in ((a,b,c),(b,a,c),(c,a,b)): dd=gcd(x-1,gcd(y,z)) arr=sorted(((x-1)//dd,y//dd,z//dd)) best=min(best,1+ff(*arr)) return best for t in [(random.randint(1,200),random.randint(1,200),random.randint(1,200)) for _ in range(20)]: g=gcd(t[0],gcd(t[1],t[2])) u=tuple(sorted(x//g for x in t)) seen=0 ff.cache_clear() ans=ff(*u) print(t,u,ans, "states", ff.cache_info().currsize)
pythonfrom collections import deque def solve_path(a,b,c): g=gcd(a,gcd(b,c)) start=tuple(sorted((a//g,b//g,c//g))) q=deque([start]); prev={start:None}; dist={start:0} while q: s=q.popleft() a,b,c=s if a==1: # terminal after one more? Actually dist to primitive state break for x,y,z in [(a,b,c),(b,a,c),(c,a,b)]: d=gcd(x-1,gcd(y,z)) ns=tuple(sorted(((x-1)//d,y//d,z//d))) if ns not in dist: dist[ns]=dist[s]+1 prev[ns]=(s, (x,y,z), ns) q.append(ns) # find best terminal
pythonfrom collections import deque, defaultdict def best_paths(a,b,c): g=gcd(a,gcd(b,c)) start=tuple(sorted((a//g,b//g,c//g))) q=deque([start]); dist={start:0}; parent={start:[]} while q: s=q.popleft() if dist[s]>10: break a,b,c=s for idx,(x,y,z) in enumerate([(a,b,c),(b,a,c),(c,a,b)]): d=gcd(x-1,gcd(y,z)) ns=tuple(sorted(((x-1)//d,y//d,z//d))) nd=dist[s]+1 if ns not in dist: dist[ns]=nd; parent[ns]=[(s,idx)] q.append(ns) elif nd==dist[ns]: parent[ns].append((s,idx
pythonfrom collections import deque, defaultdict from math import gcd def optimal_paths(a,b,c,limit=20): g=gcd(a,gcd(b,c)) start=tuple(sorted((a//g,b//g,c//g))) q=deque([start]); dist={start:0}; parent=defaultdict(list) while q: s=q.popleft() dcur=dist[s] if dcur>=limit: continue a,b,c=s if a==1: continue options=[(0,(a,b,c)),(1,(b,a,c)),(2,(c,a,b))] for idx,(x,y,z) in options: d=gcd(x-1,gcd(y,z)) ns=tuple(sorted(((x-1)//d,y//d,z//d))) nd=dcur+1 if ns not in dist: dist[ns]=nd parent[ns].append((s,idx)) q.append(ns) elif nd==dist[ns]: parent[ns].append((s,idx)) terms=[(d+1,s) for s,d in dist.items() if s[0]==1] bestcost,best=min(terms) return start, bestcost, best, dist, parent start,bestcost,best,dist,parent=optimal_paths(9,25,37,10) start,bestcost,best ((9, 25, 37), 4, (1, 4, 6))
pythonfrom math import gcd def greedy(a,b,c,rule=0): g=gcd(a,gcd(b,c)) a,b,c=sorted((a//g,b//g,c//g)) steps=0 while a>0: if a==1: return steps+1 opts=[] triples=[(a,b,c),(b,a,c),(c,a,b)] for idx,(x,y,z) in enumerate(triples): d=gcd(x-1,gcd(y,z)) ns=tuple(sorted(((x-1)//d,y//d,z//d))) # metrics if rule==0: key=(-d, ns[0], sum(ns)) elif rule==1: key=(ns[0], sum(ns), -d) elif rule==2: key=(sum(ns), ns[0], -d) elif rule==3: key=(-d, sum(ns), ns[0]) opts.append((key,ns)) opts.sort(key=lambda x:x[0]) a,b,c=opts[0][1] steps+=1 return steps def trueans(t): from functools import lru_cache g=gcd(t[0],gcd(t[1],t[2])) @lru_cache(None) def f(a,b,c): a,b,c=sorted((a,b,c)) if a==0:return 0 if a==1:return 1 best=a for x,y,z in [(a,b,c),(b,a,c),(c,a,b)]: d=gcd(x-1,gcd(y,z)) ns=tuple(sorted(((x-1)//d,y//d,z//d))) best=min(best,1+f(*ns)) return best return f(*sorted((t[0]//g,t[1]//g,t[2]//g))) for rule in range(4): bad=0 maxbad=[] for a in range(1,21): for b in range(a,21): for c in range(b,21): if gcd(a,gcd(b,c))!=1: continue ta=trueans((a,b,c)) ga=greedy(a,b,c,rule) if ta!=ga: bad+=1 if len(maxbad)<10:maxbad.append(((a,b,c),ta,ga)) print(rule,bad,maxbad[:10])
pythonfrom math import gcd mx=0 arg=None for a in range(1,31): for b in range(a,31): for c in range(b,31): if gcd(a,gcd(b,c))!=1: continue ta=trueans((a,b,c)) if ta>mx: mx=ta; arg=(a,b,c) mx,arg (8, (17, 23, 23))
python# compute max cost up to 50 might be huge; let's maybe up to 35 mx=0; arg=None for a in range(1,36): for b in range(a,36): for c in range(b,36): if gcd(a,gcd(b,c))!=1: continue ta=trueans((a,b,c)) if ta>mx: mx=ta; arg=(a,b,c) mx,arg (9, (23, 27, 35))
python# compute max cost up to 50 might be huge; let's maybe up to 35 mx=0; arg=None for a in range(1,36): for b in range(a,36): for c in range(b,36): if gcd(a,gcd(b,c))!=1: continue ta=trueans((a,b,c)) if ta>mx: mx=ta; arg=(a,b,c) mx,arg (9, (23, 27, 35))
pythonfrom collections import deque from math import gcd def bfs_ans(l,b,h,limit_states=2_000_000): g=gcd(l,gcd(b,h)) start=tuple(sorted((l//g,b//g,h//g))) if start[0]==1: return 1,1 q=deque([start]); dist={start:0} while q: s=q.popleft() d=dist[s] a,b,c=s for x,y,z in [(a,b,c),(b,a,c),(c,a,b)]: dd=gcd(x-1,gcd(y,z)) ns=tuple(sorted(((x-1)//dd,y//dd,z//dd))) if ns[0]==1: return d+2, len(dist) if ns not in dist: dist[ns]=d+1 q.append(ns) if len(dist)>limit_states: return None,len(dist) return None,len(dist) for t in [(185,67,166),(61,128,168),(9,25,37),(4,5,5)]: print(t,bfs_ans(*t))
pythonimport random, math, statistics, time samples=[] mxs=0 mxstate=None for _ in range(200): t=(random.randint(1,300),random.randint(1,300),random.randint(1,300)) ans,states=bfs_ans(*t,limit_states=1_000_000) samples.append(states) if states>mxs: mxs=states; mxstate=(t,ans,states) mxs,mxstate, statistics.mean(samples), statistics.median(samples) (691, ((247, 139, 203), 12, 691), 125.08, 86.0)
Use BFS on the normalized state (l/g, b/g, h/g), where g = gcd(l,b,h).
Reason:
(a,b,c), choosing one side x means:
1((x-1)/d, y/d, z/d) where d = gcd(x-1, gcd(y,z)).Paste this C++ code:
cpp#include <bits/stdc++.h> using namespace std; struct State { long long a, b, c; bool operator==(const State &other) const { return a == other.a && b == other.b && c == other.c; } }; struct StateHash { size_t operator()(const State &s) const { size_t h1 = hash<long long>{}(s.a); size_t h2 = hash<long long>{}(s.b); size_t h3 = hash<long long>{}(s.c); return h1 ^ (h2 << 1) ^ (h3 << 2); } }; int boxVolume(int input1, int input2, int input3) { long long l = input1, b = input2, h = input3; long long g = std::gcd(l, std::gcd(b, h)); l /= g; b /= g; h /= g; vector<long long> v = {l, b, h}; sort(v.begin(), v.end()); State start{v[0], v[1], v[2]}; // If smallest normalized side is 1, one more operation makes it 0 if (start.a == 1) return 1; queue<State> q; unordered_set<State, StateHash> vis; q.push(start); vis.insert(start); int steps = 0; while (!q.empty()) { int sz = (int)q.size(); while (sz--) { State cur = q.front(); q.pop(); if (cur.a == 1) return steps + 1; long long arr[3] = {cur.a, cur.b, cur.c}; for (int i = 0; i < 3; i++) { long long x = arr[i]; long long y = arr[(i + 1) % 3]; long long z = arr[(i + 2) % 3]; long long d = std::gcd(x - 1, std::gcd(y, z)); vector<long long> nxt = { (x - 1) / d, y / d, z / d }; sort(nxt.begin(), nxt.end()); State ns{nxt[0], nxt[1], nxt[2]}; if (!vis.count(ns)) { vis.insert(ns); q.push(ns); } } } steps++; } return -1; // should never happen }
For your examples:
4 7 8 -> 39 25 37 -> 4give code in cpp
Use this C++ solution for the stated condition make total sum of weights <= K:
cpp#include <bits/stdc++.h> using namespace std; // Read only region start int festivalorders(int input1, int input2, int input3[]) { int n = input1; long long k = input2; vector<long long> a(n); long long sum = 0; for (int i = 0; i < n; i++) { a[i] = input3[i]; sum += a[i]; } if (sum <= k) return 0; sort(a.begin(), a.end()); long long ans = LLONG_MAX; long long takenFromEnd = 0; // sum of x largest elements for (int x = 0; x < n; x++) { if (x > 0) { takenFromEnd += a[n - x]; } // After setting x largest elements equal to the smallest element // (possibly after decreasing the smallest), compute required decrements. long long need = sum - takenFromEnd + 1LL * x * a[0] - k; long long y = 0; // number of "-1" operations on smallest element if (need > 0) { y = (need + x) / (x + 1); // ceil(need / (x+1)) } ans = min(ans, x + y); } return (int)ans; } // Read only region end
This is the optimal O(n log n) approach.
If your platform is expecting the screenshot’s second example output 3 for {1,2,3,4}, K=16, then that example is inconsistent with the written condition sum <= K.
give me code in cpp
pythondef next_state(p): n=len(p) s='' for i in range(n): l=p[(i-1)%n] r=p[(i+1)%n] s += str((int(p[i]) ^ (int(l)^int(r)))) return s print(next_state('1011000'))
pythondef prevs(s): n=len(s) out=[] for x in range(1<<n): p=''.join('1' if x>>i&1 else '0' for i in range(n)) if next_state(p)==s: out.append(p) return out print(prevs('000'))
pythondef solve(s): n=len(s) if n<=2: return s sols=[] for b0 in [0,1]: for b1 in [0,1]: p=[0]*n p[0]=b0;p[1]=b1 for i in range(1,n-1): p[i+1]=(ord(s[i])-48)^p[i]^p[i-1] if (p[n-1]^p[0]^p[1])==(ord(s[0])-48) and (p[n-2]^p[n-1]^p[0])==(ord(s[n-1])-48): sols.append(''.join(map(str,p))) sols=sorted(set(sols)) if not sols:return "No Chance" if len(sols)>1:return "Multiple scenario" return sols[0] print(solve('1000101')) print(solve('000')) for s in ['0','1','00','01','10','11','001','010','011','111']: print(s, solve(s), prevs(s))
Paste this C++ code:
cpp#include <bits/stdc++.h> using namespace std; // Read only region start string circularCircuit(string input1) { string s = input1; int n = (int)s.size(); // For 1 or 2 LEDs, both neighbors are effectively the same, // so no LED changes state. if (n <= 2) return s; int cnt = 0; string ans = ""; // Try all possibilities for first two bits of previous day for (int b0 = 0; b0 <= 1; b0++) { for (int b1 = 0; b1 <= 1; b1++) { vector<int> prev(n); prev[0] = b0; prev[1] = b1; // current[i] = prev[i-1] xor prev[i] xor prev[i+1] // => prev[i+1] = current[i] xor prev[i] xor prev[i-1] for (int i = 1; i <= n - 2; i++) { prev[i + 1] = (s[i] - '0') ^ prev[i] ^ prev[i - 1]; } // Check circular conditions for positions 0 and n-1 bool ok1 = ((prev[n - 1] ^ prev[0] ^ prev[1]) == (s[0] - '0')); bool ok2 = ((prev[n - 2] ^ prev[n - 1] ^ prev[0]) == (s[n - 1] - '0')); if (ok1 && ok2) { cnt++; if (cnt == 1) { ans.clear(); for (int x : prev) ans.push_back(char('0' + x)); } else { return "Multiple scenario"; } } } } if (cnt == 0) return "No Chance"; return ans; } // Read only region end
For the example:
1000101 → 1011000000 → Multiple scenarioIf your judge expects Multiple Scenario with capital S, just change that one return string.
optimized it " #include <bits/stdc++.h>
using namespace std;
// Read only region start
string circularCircuit(string input1)
{
string s = input1;
int n = (int)s.size();
text// For 1 or 2 LEDs, both neighbors are effectively the same, // so no LED changes state. if (n <= 2) return s; int cnt = 0; string ans = ""; // Try all possibilities for first two bits of previous day for (int b0 = 0; b0 <= 1; b0++) { for (int b1 = 0; b1 <= 1; b1++) { vector<int> prev(n); prev[0] = b0; prev[1] = b1; // current[i] = prev[i-1] xor prev[i] xor prev[i+1] // => prev[i+1] = current[i] xor prev[i] xor prev[i-1] for (int i = 1; i <= n - 2; i++) { prev[i + 1] = (s[i] - '0') ^ prev[i] ^ prev[i - 1]; } // Check circular conditions for positions 0 and n-1 bool ok1 = ((prev[n - 1] ^ prev[0] ^ prev[1]) == (s[0] - '0')); bool ok2 = ((prev[n - 2] ^ prev[n - 1] ^ prev[0]) == (s[n - 1] - '0')); if (ok1 && ok2) { cnt++; if (cnt == 1) { ans.clear(); for (int x : prev) ans.push_back(char('0' + x)); } else { return "Multiple scenario"; } } } } if (cnt == 0) return "No Chance"; return ans;
}
// Read only region end
Your logic is already asymptotically optimal at O(n).
I cleaned it up and reduced overhead by using a string instead of vector<int>.
cpp#include <bits/stdc++.h> using namespace std; // Read only region start string circularCircuit(string input1) { const string &s = input1; int n = (int)s.size(); if (n <= 2) return s; string answer = ""; bool found = false; for (int first = 0; first <= 1; first++) { for (int second = 0; second <= 1; second++) { string prev(n, '0'); prev[0] = char('0' + first); prev[1] = char('0' + second); for (int i = 1; i < n - 1; i++) { prev[i + 1] = char('0' + ((s[i] - '0') ^ (prev[i] - '0') ^ (prev[i - 1] - '0'))); } if ((((prev[n - 1] - '0') ^ (prev[0] - '0') ^ (prev[1] - '0')) == (s[0] - '0')) && (((prev[n - 2] - '0') ^ (prev[n - 1] - '0') ^ (prev[0] - '0')) == (s[n - 1] - '0'))) { if (found) return "Multiple scenario"; found = true; answer = prev; } } } return found ? answer : "No Chance"; } // Read only region end
Complexity:
O(n)O(n) for the output candidate stringIf you want, I can also give an even more compact version with a small helper lambda.
If you want, I can also give an even more compact version with a small helper lambda.
Here’s a more compact O(n) version with a helper lambda:
cpp#include <bits/stdc++.h> using namespace std; // Read only region start string circularCircuit(string input1) { int n = (int)input1.size(); if (n <= 2) return input1; auto build = [&](int b0, int b1) -> string { string p(n, '0'); p[0] = char('0' + b0); p[1] = char('0' + b1); for (int i = 1; i < n - 1; i++) { p[i + 1] = char('0' + ((input1[i] - '0') ^ (p[i] - '0') ^ (p[i - 1] - '0'))); } if (((p[n - 1] - '0') ^ (p[0] - '0') ^ (p[1] - '0')) != (input1[0] - '0')) return ""; if (((p[n - 2] - '0') ^ (p[n - 1] - '0') ^ (p[0] - '0')) != (input1[n - 1] - '0')) return ""; return p; }; string ans = ""; for (int b0 = 0; b0 <= 1; b0++) { for (int b1 = 0; b1 <= 1; b1++) { string cur = build(b0, b1); if (cur.empty()) continue; if (!ans.empty()) return "Multiple scenario"; ans = cur; } } return ans.empty() ? "No Chance" : ans; } // Read only region end
This keeps the same complexity:
O(n)O(n)And for stricter judges, you may need to replace "Multiple scenario" with "Multiple Scenario" depending on exact expected output.
optimized it" #include <bits/stdc++.h>
using namespace std;
struct State {
long long a, b, c;
bool operator==(const State &other) const {
return a == other.a && b == other.b && c == other.c;
}
};
struct StateHash {
size_t operator()(const State &s) const {
size_t h1 = hash<long long>{}(s.a);
size_t h2 = hash<long long>{}(s.b);
size_t h3 = hash<long long>{}(s.c);
return h1 ^ (h2 << 1) ^ (h3 << 2);
}
};
int boxVolume(int input1, int input2, int input3)
{
long long l = input1, b = input2, h = input3;
textlong long g = std::gcd(l, std::gcd(b, h)); l /= g; b /= g; h /= g; vector<long long> v = {l, b, h}; sort(v.begin(), v.end()); State start{v[0], v[1], v[2]}; // If smallest normalized side is 1, one more operation makes it 0 if (start.a == 1) return 1; queue<State> q; unordered_set<State, StateHash> vis; q.push(start); vis.insert(start); int steps = 0; while (!q.empty()) { int sz = (int)q.size(); while (sz--) { State cur = q.front(); q.pop(); if (cur.a == 1) return steps + 1; long long arr[3] = {cur.a, cur.b, cur.c}; for (int i = 0; i < 3; i++) { long long x = arr[i]; long long y = arr[(i + 1) % 3]; long long z = arr[(i + 2) % 3]; long long d = std::gcd(x - 1, std::gcd(y, z)); vector<long long> nxt = { (x - 1) / d, y / d, z / d }; sort(nxt.begin(), nxt.end()); State ns{nxt[0], nxt[1], nxt[2]}; if (!vis.count(ns)) { vis.insert(ns); q.push(ns); } } } steps++; } return -1; // should never happen
}
pythonfrom functools import lru_cache from math import gcd from collections import deque def bfs(a,b,c, limit=100000): g=gcd(a,gcd(b,c)) a//=g;b//=g;c//=g s=tuple(sorted((a,b,c))) q=deque([(s,0)]) vis={s} while q: (x,y,z),d=q.popleft() if x==0: return d g=gcd(x,gcd(y,z)) assert g==1 if x==1: return d+1 arr=[x,y,z] for i in range(3): if arr[i]==0: return d u=arr.copy() u[i]-=1 g=gcd(u[0],gcd(u[1],u[2])) u=tuple(sorted((u[0]//g,u[1]//g,u[2]//g))) if u not in vis: vis.add(u) q.append((u,d+1)) return None vals={} for a in range(1,11): for b in range(1,11): for c in range(1,11): vals[(a,b,c)] = bfs(a,b,c) # sample few list(vals.items())[:5]
pythonfrom functools import lru_cache from math import gcd from collections import deque def minops(a,b,c): g=gcd(a,gcd(b,c)) a//=g;b//=g;c//=g s=tuple(sorted((a,b,c))) q=deque([(s,0)]) vis={s} while q: (x,y,z),d=q.popleft() if x==0: return d if x==1: return d+1 arr=[x,y,z] for i in range(3): u=arr.copy() u[i]-=1 if u[i] < 0: continue gg=gcd(u[0],gcd(u[1],u[2])) u=tuple(sorted((u[0]//gg,u[1]//gg,u[2]//gg))) if u not in vis: vis.add(u) q.append((u,d+1)) return None for t in [(4,7,8),(9,25,37)]: print(t,minops(*t))
pythonfrom math import gcd def norm(a,b,c): g=gcd(a,gcd(b,c)) a//=g;b//=g;c//=g return tuple(sorted((a,b,c))) res={} for a in range(1,11): for b in range(a,11): for c in range(b,11): res[(a,b,c)] = minops(a,b,c) # print small for k,v in list(res.items())[:20]: print(k, norm(*k), v)
pythonfor a in range(2,8): rows=[] for b in range(a,8): for c in range(b,8): rows.append((a,b,c,minops(a,b,c))) print("a=",a, rows[:10], "...")
pythonfrom math import gcd from collections import defaultdict, deque def path(a,b,c): g=gcd(a,gcd(b,c)) s=tuple(sorted((a//g,b//g,c//g))) q=deque([s]); parent={s:None}; dist={s:0} while q: cur=q.popleft() x,y,z=cur if x==1: seq=[] while cur is not None: seq.append(cur); cur=parent[cur] return dist[(x,y,z)]+1, seq[::-1] arr=[x,y,z] for i in range(3): u=arr.copy(); u[i]-=1 gg=gcd(u[0],gcd(u[1],u[2])) ns=tuple(sorted((u[0]//gg,u[1]//gg,u[2]//gg))) if ns not in dist: dist[ns
pythonfrom functools import lru_cache from math import gcd,isqrt def normalize(t): a,b,c=t arr=sorted((a,b,c)) g=gcd(arr[0],gcd(arr[1],arr[2])) return tuple(x//g for x in arr) @lru_cache(None) def rec(state): a,b,c=state if a==0: return 0 ans=a mx=c for d in range(2,mx+1): na=a-a%d nb=b-b%d nc=c-c%d cost=(a%d)+(b%d)+(c%d) if na==0 or nb==0 or nc==0: ans=min(ans,cost) # because if any zero after decrements else: ns=normalize((na//d,nb//d,nc//d)) ans=min(ans,cost+rec(ns)) return ans ok=True for a in range(1,9): for b in range(a,9): for c in range(b,9): x=minops(a,b,c) y=rec(normalize((a,b,c))) if x!=y: print("mismatch", (a,b,c), x,y) ok=False raise SystemExit print("all ok")
pythonfrom functools import lru_cache from math import gcd def normt(a,b,c): g=gcd(a,gcd(b,c)) arr=sorted((a//g,b//g,c//g)) return tuple(arr) @lru_cache(None) def rec2(state): a,b,c=state if a<=1: return a ans=a d=2 while d<=a: qa,qb,qc = a//d, b//d, c//d r=min(a//qa, b//qb, c//qc, a) cost = (a+b+c) - r*(qa+qb+qc) ns=normt(qa,qb,qc) ans=min(ans, cost + rec2(ns)) d=r+1 return ans for a in range(1,30): for b in range(a,30): for c in range(b,30): x=minops(a,b,c) y=rec2(normt(a,b,c)) if x!=y: print("mismatch", (a,b,c), x,y) raise SystemExit print("all ok")
pythonfrom math import gcd from collections import deque def minops(a,b,c): g=gcd(a,gcd(b,c)) a//=g;b//=g;c//=g s=tuple(sorted((a,b,c))) q=deque([(s,0)]) vis={s} while q: (x,y,z),d=q.popleft() if x==0: return d if x==1: return d+1 arr=[x,y,z] for i in range(3): u=arr.copy() u[i]-=1 gg=gcd(u[0],gcd(u[1],u[2])) ns=tuple(sorted((u[0]//gg,u[1]//gg,u[2]//gg))) if ns not in vis: vis.add(ns); q.append((ns,d+1)) def normt(a,b,c): g=gcd(a,gcd(b,c)) return tuple(sorted((a//g,b//g,c//g))) state=normt(7,10,10) print("state",state, "bfs", minops(*state)) a,b,c=state for d in range(2,a+1): qa,qb,qc=a//d,b//d,c//d cost=(a%d)+(b%d)+(c%d) ns=normt(qa,qb,qc) print("d",d,"q",(qa,qb,qc),"cost",cost,"total",cost+(0 if qa==0 else None or 0))
pythonfrom functools import lru_cache from math import gcd def normt(a,b,c): g=gcd(a,gcd(b,c)) return tuple(sorted((a//g,b//g,c//g))) @lru_cache(None) def rec(state): a,b,c=state ans=a for d in range(2,a+1): qa,qb,qc = a//d,b//d,c//d cost=(a%d)+(b%d)+(c%d) ans=min(ans, cost + rec(normt(qa,qb,qc))) if a==1: ans=1 return ans state=(7,10,10) print(rec(state)) for d in range(2,state[0]+1): ns=normt(state[0]//d,state[1]//d,state[2]//d) print(d, (state[0]%d)+(state[1]%d)+(state[2]%d), ns, rec(ns), (state[0]%d)+(state[1]%d)+(state[2]%d)+rec(ns))
pythonfrom math import gcd from collections import deque def bfs_stats(a,b,c): g=gcd(a,gcd(b,c)); a//=g;b//=g;c//=g s=tuple(sorted((a,b,c))) q=deque([(s,0)]); vis={s} while q: cur,d=q.popleft() x,y,z=cur if x==1: return d+1, len(vis) arr=[x,y,z] for i in range(3): u=arr.copy(); u[i]-=1 gg=gcd(u[0],gcd(u[1],u[2])) ns=tuple(sorted((u[0]//gg,u[1]//gg,u[2]//gg))) if ns not in vis: vis.add(ns); q.append((ns,d+1)) return None, len(vis) for t in [(100,101,102),(100,1000,1001),(1000,1001,1002),(1000,1999,2001)]: print(t,bfs_stats(*t))
pythonfrom functools import lru_cache from math import gcd def sort3(a,b,c): if a>b: a,b=b,a if b>c: b,c=c,b if a>b: a,b=b,a return a,b,c @lru_cache(None) def dfs(state): a,b,c=state if a==1: return 1 ans=10**9 arr=[a,b,c] for i in range(3): x,y,z=arr[i],arr[(i+1)%3],arr[(i+2)%3] d=gcd(x-1,gcd(y,z)) ns=sort3((x-1)//d, y//d, z//d) ans=min(ans,1+dfs(ns)) return ans for a in range(1,20): for b in range(a,20): for c in range(b,20): if bfs:=minops(a,b,c) != dfs(sort3(*normt(a,b,c))): print("mismatch",a,b,c,bfs,dfs(sort3(*normt(a,b,c)))) raise SystemExit print("ok")
Here’s a faster version of your solution.
What changed:
vector allocations inside transitionssort3cpp#include <bits/stdc++.h> using namespace std; using ll = long long; using u128 = __uint128_t; struct U128Hash { size_t operator()(u128 x) const { uint64_t lo = (uint64_t)x; uint64_t hi = (uint64_t)(x >> 64); return (size_t)(lo ^ (hi * 11995408973635179863ULL)); } }; static unordered_map<u128, int, U128Hash> memo; static inline void sort3(ll &a, ll &b, ll &c) { if (a > b) swap(a, b); if (b > c) swap(b, c); if (a > b) swap(a, b); } static inline u128 makeKey(ll a, ll b, ll c) { return ((u128)a << 84) | ((u128)b << 42) | (u128)c; } static inline void normalize(ll &a, ll &b, ll &c) { ll g = gcd(a, gcd(b, c)); a /= g; b /= g; c /= g; sort3(a, b, c); } static int solve(ll a, ll b, ll c) { if (a == 1) return 1; u128 key = makeKey(a, b, c); auto it = memo.find(key); if (it != memo.end()) return it->second; int ans = INT_MAX; auto relax = [&](ll x, ll y, ll z) { normalize(x, y, z); ans = min(ans, 1 + solve(x, y, z)); }; // Decrease smallest side relax(a - 1, b, c); // Decrease middle side (skip duplicate state if a == b) if (b != a) relax(a, b - 1, c); // Decrease largest side (skip duplicate state if b == c) if (c != b) relax(a, b, c - 1); return memo[key] = ans; } // Read only region start int boxVolume(int input1, int input2, int input3) { ll a = input1, b = input2, c = input3; normalize(a, b, c); memo.clear(); memo.reserve(1 << 16); return solve(a, b, c); } // Read only region end
This keeps the same exact result, but is noticeably leaner than the BFS version.
give code in c++
pythonfrom functools import lru_cache def pairings(arr): arr=tuple(arr) @lru_cache(None) def rec(state): n=len(state) if n==0: return {()} if n==2: return {((state[0],state[1]),)} mid=n//2 # 0-based second middle? len even => mid index inds=[0,mid,n-1] pairs=[(0,mid),(0,n-1),(mid,n-1)] res=set() for i,j in pairs: if i==j: continue rem=tuple(state[k] for k in range(n) if k not in (i,j)) for rest in rec(rem): p=tuple(sorted((state[i],state[j]))) res.add(tuple(sorted((p,)+rest))) return res return rec(arr) for n in [4,6,8]: arr=tuple(range(1,n+1)) ps=pairings(arr) print(n,len(ps)) # maybe display if n<=6: for p in sorted(ps)[:50]: print(p) print()
pythonfrom functools import lru_cache from math import gcd def brute(a): a=tuple(a) @lru_cache(None) def rec(state): n=len(state) if n==0: return 0 if n==2: return gcd(state[0],state[1]) mid=n//2 best=10**9 for i,j in [(0,mid),(0,n-1),(mid,n-1)]: rem=tuple(state[k] for k in range(n) if k not in (i,j)) best=min(best,gcd(state[i],state[j])+rec(rem)) return best return rec(a) def dp(arr): n=len(arr) a=[0]+arr from functools import lru_cache @lru_cache(None) def C(l,r): if l>r: return 0 if r-l+1==2: return gcd(a[l],a[r]) L=r-l+1 k=L//2 mid=l+k return min( gcd(a[l],a[r]) + C(l+1,r-1), gcd(a[l],a[mid]) + E(l+1, mid+1, r), gcd(a[mid],a[r]) + D(l, mid+1, r-1) ) @lru_cache(None) def E(l,m,r): # A len = B len = r-m+1 k=r-m+1 if k==1: return gcd(a[l],a[m]) return min( gcd(a[l],a[m]) + E(l+1,m+1,r), gcd(a[l],a[r]) + E(l+1,m,r-1), gcd(a[m],a[r]) + D(l,m+1,r-1) ) @lru_cache(None) def D(l,m,r): # A len = B len +2 k=r-m+1 if k==0: # only A len2? return gcd(a[l],a[l+1]) aend=l+k+1 return min( gcd(a[l],a[aend]) + E(l+1,m,r), gcd(a[l],a[r]) + D(l+1,m,r-1), gcd(a[aend],a[r]) + D(l,m,r-1) ) return C(1,n) import random for n in [2,4,6,8]: for _ in range(200): arr=[random.randint(1,20) for _ in range(n)] b=brute(arr) d=dp(arr) if b!=d: print("mismatch",n,arr,b,d) raise SystemExit print("all ok")
Use this C++ code:
cpp#include <bits/stdc++.h> using namespace std; static vector<long long> E; static vector<vector<long long>> memoC; static unordered_map<long long, long long> memoEq, memoDf; static long long gcdll(long long a, long long b) { while (b) { long long t = a % b; a = b; b = t; } return a; } static long long makeKey(int l, int m, int r) { return ( (long long)l << 40 ) | ( (long long)m << 20 ) | (long long)r; } // One contiguous segment: [l ... r] static long long solveC(int l, int r); // Two segments of equal length: // [l ... x] and [m ... r] static long long solveEq(int l, int m, int r); // Two segments where first is longer by 2: // [l ... x] and [m ... r] static long long solveDf(int l, int m, int r); static long long solveC(int l, int r) { if (l > r) return 0; if (memoC[l][r] != -1) return memoC[l][r]; if (r - l + 1 == 2) { return memoC[l][r] = gcdll(E[l], E[r]); } int len = r - l + 1; int mid = l + len / 2; // second middle long long ans = LLONG_MAX; // pair start and end ans = min(ans, gcdll(E[l], E[r]) + solveC(l + 1, r - 1)); // pair start and middle ans = min(ans, gcdll(E[l], E[mid]) + solveEq(l + 1, mid + 1, r)); // pair middle and end ans = min(ans, gcdll(E[mid], E[r]) + solveDf(l, mid + 1, r - 1)); return memoC[l][r] = ans; } static long long solveEq(int l, int m, int r) { long long key = makeKey(l, m, r); auto it = memoEq.find(key); if (it != memoEq.end()) return it->second; int k = r - m + 1; // length of right segment, same as left segment if (k == 1) { return memoEq[key] = gcdll(E[l], E[m]); } long long ans = LLONG_MAX; // pair start of left and start of right ans = min(ans, gcdll(E[l], E[m]) + solveEq(l + 1, m + 1, r)); // pair start of left and end of right ans = min(ans, gcdll(E[l], E[r]) + solveEq(l + 1, m, r - 1)); // pair start of right and end of right ans = min(ans, gcdll(E[m], E[r]) + solveDf(l, m + 1, r - 1)); return memoEq[key] = ans; } static long long solveDf(int l, int m, int r) { long long key = makeKey(l, m, r); auto it = memoDf.find(key); if (it != memoDf.end()) return it->second; int k = (m <= r ? (r - m + 1) : 0); // length of right segment int endLeft = l + k + 1; // left segment length = k + 2 if (k == 0) { return memoDf[key] = gcdll(E[l], E[l + 1]); } long long ans = LLONG_MAX; // pair start and second-middle (= end of left segment) ans = min(ans, gcdll(E[l], E[endLeft]) + solveEq(l + 1, m, r)); // pair start and end ans = min(ans, gcdll(E[l], E[r]) + solveDf(l + 1, m, r - 1)); // pair second-middle and end ans = min(ans, gcdll(E[endLeft], E[r]) + solveDf(l, m, r - 1)); return memoDf[key] = ans; } // Read only region start int destroyMonsters(int input1, int input2[]) { int n = input1; E.assign(n + 1, 0); for (int i = 1; i <= n; i++) E[i] = input2[i - 1]; memoC.assign(n + 2, vector<long long>(n + 2, -1)); memoEq.clear(); memoDf.clear(); return (int)solveC(1, n); } // Read only region end
For the examples:
{1,4,9,6} → 2{2,8,16,12} → 6is that i can replace it with any other return (size_t)(lo ^ (hi * 11995408973635179863ULL));
Yes, you can replace it.
That line is only a hash-mixing function for combining the low 64 bits and high 64 bits of __uint128_t. It does not affect correctness of the algorithm, only the quality of hashing in unordered_map or unordered_set.
A simpler replacement is:
cppreturn (size_t)(lo ^ (hi << 1));
A better common combiner is:
cppreturn (size_t)(lo ^ (hi + 0x9e3779b97f4a7c15ULL + (lo << 6) + (lo >> 2)));
So your hash can be:
cppstruct U128Hash { size_t operator()(__uint128_t x) const { uint64_t lo = (uint64_t)x; uint64_t hi = (uint64_t)(x >> 64); return (size_t)(lo ^ (hi + 0x9e3779b97f4a7c15ULL + (lo << 6) + (lo >> 2))); } };
Use this rule:
So yes, that constant 11995408973635179863ULL is not mandatory. It was just one arbitrary large odd number used for mixing.