├── .editorconfig ├── 2016_RoundA ├── JaneFlowerShop.cpp ├── README.md ├── clashRoyale.cpp ├── countryLeader.py └── rain.py ├── 2016_RoundB ├── README.md ├── SherlockAndPermutationSorting.cpp ├── sherlockAndGymSecrets.cpp ├── sherlockAndParentheses.py └── watsonAndIntervals.cpp ├── 2016_RoundC ├── README.md ├── evaluation.py ├── monsterPath.py ├── safeSquares.cpp └── soldiers.cpp ├── 2016_RoundD ├── README.md ├── codejamonCipher.cpp ├── sitting.py ├── stretchRope.cpp └── vote.cpp ├── 2016_RoundE ├── README.md ├── beautifulNumbers.py ├── diwaliLightings.py ├── helper.py ├── partitioningNumber.cpp └── sortingArray.cpp ├── 2017_RoundA ├── README.md ├── patternOverlap.cpp ├── squareCounting.py └── twoCubes.cpp ├── 2017_RoundB ├── ChristmasTree.cpp ├── README.md ├── center.cpp └── mathEncoder.cpp ├── 2017_RoundC ├── 4MCorporation.py ├── README.md ├── Xsquared.py ├── ambiguousCipher.py └── magicalThinking.py ├── 2017_RoundD ├── README.md ├── sherlockAndTheMatrixGame.cpp └── sightSeeing.cpp ├── 2017_RoundE ├── README.md ├── blackhole-small.cpp ├── copyPaste.cpp └── trapezoidCounting.py ├── 2017_RoundF ├── README.md ├── cake.cpp ├── catchThemAll.cpp ├── danceBattle.cpp └── kickSort.cpp ├── 2017_RoundG ├── README.md ├── cardsGame.py ├── hugeNumber.py └── matrixCutting.cpp ├── 2018_RoundA ├── README.md ├── evenDigits.py ├── luckyDip.cpp └── scrambledWords.cpp ├── 2018_RoundB ├── README.md ├── SherlockAndBitStrings.cpp ├── kingsCircle.cpp └── noNine.py ├── 2018_RoundC ├── README.md ├── fairiesAndWitches.cpp ├── kickstartAlarm.cpp └── planetDistance.py ├── 2018_RoundD ├── README.md ├── candies.cpp ├── funniestWordSearch.cpp └── paraGliding.cpp ├── 2018_RoundE ├── README.md ├── boardGame.cpp ├── milkTea.py └── yogurt.py ├── 2018_RoundF ├── README.md ├── commonAnagrams.py ├── helper.cpp ├── palidromicSequence.py └── specializingVillages.py ├── 2018_RoundG ├── README.md ├── caveEscape.cpp ├── combiningClasses.cpp └── productTriplet.cpp ├── 2018_RoundH ├── README.md ├── bigButtons.py ├── countTheWays.cpp └── mural.py ├── 2019_RoundA ├── Parcels.py ├── README.md ├── contention.cpp └── training.py ├── 2019_RoundB ├── README.md ├── buildingPalindromes.py ├── diverseSubarray.cpp └── energyStones.py ├── 2019_RoundC ├── README.md ├── catchSome.py ├── circuitBoard.py └── wiggleWalk.py ├── 2019_RoundD ├── README.md ├── XorWhat.py ├── foodStall.py ├── latestGuests.cpp └── latestGuests.py ├── 2019_RoundE ├── README.md ├── cherries.py ├── codeEat.py └── streetChecker.py ├── 2019_RoundF ├── README.md ├── flattening.py ├── teachMe.py ├── villages.cpp └── villages.py ├── 2019_RoundG ├── README.md ├── bookReading.py ├── equation.py └── shifts.py ├── 2019_RoundH ├── README.md ├── diagonalPuzzle.py ├── elevanagram.py └── h-index.py ├── 2019_practiceRound ├── README.md ├── kickstartAlarm.cpp ├── mural.py └── numberGuessing.py ├── 2020_RoundA ├── bundling.py ├── plate.py └── workout.py ├── 2020_RoundB ├── README.md ├── p1.py ├── p2.py ├── p3.py ├── p4.py ├── ref.py ├── robot.cpp └── robot.o ├── 2020_RoundC ├── README.md ├── candies-biTree.cpp ├── candies-segment.cpp ├── countdown.py ├── perfectSubarray.cpp └── stableWall.py ├── 2020_RoundD ├── README.md ├── alienPiano.py ├── beautyTree.cpp ├── lockedDoors.cpp └── lockedDoors.pdf ├── 2020_RoundE ├── README.md ├── goldenStone.cpp ├── highBuildings.py ├── longestArithmetic.py └── toys.cpp ├── 2020_RoundF ├── ATMQueue.cpp ├── PaintersDuel.cpp ├── README.md ├── helper.py ├── large-in-3.txt ├── large-out-3.txt ├── metalHarvest.py └── yeetzhee.cpp ├── 2020_RoundG ├── Kick_Start.py ├── README.md ├── combinationLock.cpp ├── maximumCoins.py └── mergeCards.cpp ├── 2020_RoundH ├── README.md ├── boringNumbers.py ├── friends.cpp ├── retype.py └── rugby.cpp ├── 2021_RoundA ├── K_goodness.py ├── LShapedPlots.py ├── README.md ├── checksum.py └── rabbitHouse.py ├── 2021_RoundB ├── README.md ├── consecutivePrimes.py ├── increasingSubstring.py ├── longestRegression.py └── truckDelivery.cpp ├── 2021_RoundC ├── README.md ├── RockPaperScissors.cpp ├── alienGenerator.py ├── binaryOperator.py └── smallerStrings.py ├── 2021_RoundD ├── README.md ├── arithmeticSquare.py ├── cuttingIntervals.py ├── finalExam.cpp └── primesAndQueries.cpp ├── 2021_RoundE ├── README.md ├── birthdayCake.py ├── increasingCardGame.py ├── palindromicCrossword.py └── shuffledAnagrams.py ├── 2021_RoundF ├── README.md ├── festival.py ├── graphTravel.cpp ├── starTrappers.py └── trashBins.py ├── 2021_RoundG ├── Banana.py ├── README.md ├── dogsAndCats.py ├── simplePolygon.py └── stayHydrated.py ├── 2021_RoundH ├── README.md ├── dependentEvents.cpp ├── painter.py ├── sillySubstitutions.py └── transformTheString.py ├── 2022_RoundA ├── README.md ├── challengeNine.py ├── interestingInteger.py ├── palindromeFree.py └── speedTyping.py ├── 2022_RoundB ├── Hamiltonian.cpp ├── README.md ├── infinityArea.py ├── palindromicFactors.py └── unlockThePadlock.py ├── 2022_RoundC ├── README.md ├── antsOnAStick.py ├── newPassword.py ├── palindromicDeletions.py └── rangePartition.py ├── 2022_RoundD ├── README.md ├── SuspectsAndWitnesses.cpp ├── imageLabeler.py ├── maximumGain.py └── touchbarTyping.py ├── 2022_RoundE ├── MatchingPalindrome.py ├── README.md ├── coloringGame.py ├── pizzaDelivery.cpp └── studentsAndMentors.cpp ├── 2022_RoundF ├── README.md ├── schedulingAMeeting.cpp ├── sortTheFabrics.py ├── storyOfSeasons.py └── waterContainerSystem.py ├── 2022_RoundG ├── Curling.py ├── README.md ├── Walktober.py ├── cuteLittleButterfly.cpp └── happySubarrays.py ├── 2022_RoundH ├── Electricity.cpp ├── MagicWellOfLillies.py ├── README.md ├── levelDesign.cpp └── runningInCircles.py └── README.md /.editorconfig: -------------------------------------------------------------------------------- 1 | # top-most EditorConfig file 2 | root = true 3 | 4 | # 4 space indentation for python files 5 | [*.py] 6 | indent_style = space 7 | indent_size = 4 -------------------------------------------------------------------------------- /2016_RoundA/JaneFlowerShop.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | const double eps=1e-8; 16 | double numbers[100]; 17 | 18 | int main(){ 19 | int T; 20 | cin>>T; 21 | for(int tt=1;tt>M; 24 | for(int i=0;i<=M;++i){ 25 | cin>>numbers[i]; 26 | } 27 | numbers[0]=-numbers[0]; 28 | double low=-1; 29 | double high=1; 30 | 31 | while(high-low>eps){ 32 | double mid=low+(high-low)/2; 33 | double p=1; 34 | double answer=0; 35 | for(int i=M;i>=0;--i){ 36 | answer+=numbers[i]*p; 37 | p*=(1+mid); 38 | } 39 | if(answer>0){low=mid;} 40 | else{high=mid;} 41 | } 42 | 43 | cout.precision(10); 44 | cout<<"Case #"<=attack. 6 | -------------------------------------------------------------------------------- /2016_RoundA/countryLeader.py: -------------------------------------------------------------------------------- 1 | from collections import Counter 2 | T=int(raw_input()) 3 | 4 | for tt in range(1,T+1): 5 | N=int(raw_input()) 6 | seq=[[] for x in range(27)] 7 | for i in range(N): 8 | word=raw_input() 9 | some=Counter(word.replace(' ','')) 10 | seq[len(some)].append(word) 11 | exp=26 12 | while len(seq[exp])==0: 13 | exp-=1 14 | seq[exp].sort() 15 | print "Case #"+str(tt)+": "+seq[exp][0] 16 | 17 | -------------------------------------------------------------------------------- /2016_RoundA/rain.py: -------------------------------------------------------------------------------- 1 | import heapq 2 | T=int(raw_input()) 3 | 4 | for tt in range(1,T+1): 5 | R,C=[int(t) for t in raw_input().split()] 6 | grid=[] 7 | for i in range(R): 8 | grid.append([int(t) for t in raw_input().split()]) 9 | 10 | seen=set() 11 | h=[] 12 | 13 | for j in range(1,C-1): 14 | heapq.heappush(h,[grid[0][j],0,j]) 15 | heapq.heappush(h,[grid[R-1][j],R-1,j]) 16 | seen.add((0,j)) 17 | seen.add((R-1,j)) 18 | 19 | for i in range(1,R-1): 20 | heapq.heappush(h,[grid[i][0],i,0]) 21 | heapq.heappush(h,[grid[i][C-1],i,C-1]) 22 | seen.add((i,0)) 23 | seen.add((i,C-1)) 24 | 25 | seen.add((0,0)) 26 | seen.add((R-1,0)) 27 | seen.add((0,C-1)) 28 | seen.add((R-1,C-1)) 29 | 30 | result=0 31 | while h: 32 | height,x,y=heapq.heappop(h) 33 | 34 | 35 | tx=[-1,0,1,0] 36 | ty=[0,1,0,-1] 37 | for n in range(4): 38 | newX=x+tx[n] 39 | newY=y+ty[n] 40 | if (newX,newY) in seen or newX<0 or newX>=R or newY<0 or newY>=C: 41 | continue 42 | if grid[newX][newY] 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | 18 | int main(){ 19 | int T; 20 | cin>>T; 21 | long long N,M; 22 | 23 | for(int tt=1;tt>N>>M; 25 | vector fact(N+1); 26 | fact[0]=1; 27 | fact[1]=1; 28 | for(int i=2;i<=N;++i){fact[i]=fact[i-1]*i%M;} 29 | 30 | vectorprime(N+1); 31 | prime[0]=0; 32 | prime[1]=1; 33 | for(int i=2;i<=N;++i){ 34 | prime[i]=fact[i]; 35 | for(int j=1;j dpSum(N+1,0); 41 | dpSum[0]=0; 42 | dpSum[1]=1; 43 | for(int i=2;i<=N;++i){ 44 | for(int j=0;j dpSquare(N+1,0); 50 | dpSquare[0]=0; 51 | dpSquare[1]=1; 52 | for(int i=2;i<=N;++i){ 53 | for(int j=0;j 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | long long A,B,N,K; 18 | long long mod=1e9+7; 19 | 20 | long long compute(long long base, long long exp){ 21 | long long ans=1; 22 | while(exp>0){ 23 | if(exp & 1) {ans=ans*base%K;} 24 | exp=(exp>>1); 25 | base=base*base%K; 26 | } 27 | return ans%K; 28 | } 29 | 30 | int main(){ 31 | int T; 32 | cin>>T; 33 | 34 | for(int tt=1;tt>A>>B>>N>>K; 37 | vector v1(K+1,0); //for the i th value, (i%K)^A=v1[i] 38 | vector c1(K,0); //for the j th value, there are c1[j] of numbers that mod K=j 39 | vector v2(K+1,0); 40 | vector c2(K,0); 41 | 42 | long long r; 43 | for(int i=1;i<=K;++i){ 44 | r=compute(i,A); 45 | v1[i]=r; 46 | c1[r]=(c1[r]+N/K)%mod; 47 | if(N%K >= i){c1[r]++;} 48 | 49 | r=compute(i,B); 50 | v2[i]=r; 51 | c2[r]=(c2[r]+N/K)%mod; 52 | if(N%K >=i){c2[r]++;} 53 | } 54 | 55 | long long result=0; 56 | for(int i=0;i=i){repeat++;} 65 | } 66 | } 67 | 68 | long long f=((result%mod-repeat%mod)+mod)%mod; 69 | 70 | cout<<"Case #"< 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | 18 | int main(){ 19 | int T; 20 | cin>>T; 21 | long long N,L1,R1,A,B,C1,C2,M,X2,Y2; 22 | 23 | for(int tt=1;tt>N>>L1>>R1>>A>>B>>C1>>C2>>M; 25 | long long X1=L1; 26 | long long Y1=R1; 27 | map>events; 28 | events[L1].push_back(1); 29 | events[R1+1].push_back(-1); 30 | for(int i=2;i<=N;++i){ 31 | long long X2=(A*X1+B*Y1+C1)%M; 32 | long long Y2=(A*Y1+B*X1+C2)%M; 33 | L1=min(X2,Y2); 34 | R1=max(X2,Y2); 35 | events[L1].push_back(i); 36 | events[R1+1].push_back(-i); 37 | X1=X2; 38 | Y1=Y2; 39 | } 40 | 41 | int count=0; 42 | int prev=-1; 43 | unordered_set ids; 44 | long long total=0; 45 | vector coveredArea(N+1,0); 46 | 47 | for(auto x:events){ 48 | if(prev>=0 && count>0){total+=x.first-prev;} 49 | if(count==1){coveredArea[*ids.begin()]+=x.first-prev;} 50 | 51 | for(int y:x.second){ 52 | if(y<0){count--;ids.erase(-y);} 53 | else{count++;ids.insert(y);} 54 | } 55 | 56 | prev=x.first; 57 | } 58 | 59 | long long maxReduce=0; 60 | for(long long ans:coveredArea){ 61 | maxReduce=max(maxReduce,ans); 62 | } 63 | long long result=total-maxReduce; 64 | cout<<"Case #"<A2>A3. And also sorted by defence (D1),(D2,D2,D2,D2),(D3)... where D1>D2>D3. During the first round, if there is no soldier with both attack==A1 and defence==D1, we will remove both (A1,A1,A1) group and (D1) group. Similarly, if there is no soldier with both attack==A2 and defence==D2, we will remove both (A2) group and (D2,D2,D2,D2) group. Let us call the pair of groups with same index, "same-level" groups (i.e. A2 and D2 are "same-level", A10 and D10 are "same-level"). We keep removing the pair of groups that is at the same level, if at certain point there is a soldier with attack==An and defence==Dn Alice will win. If such a soldier does not exist, Bob wins. We can construct how Bob wins: no matter what Alice picks, Bob will pick a complement soldier that is at the same-level with what Alice picks. e.g. if Alice picks A19, Bob will pick D19, if later Alice picks A5, Bob will pick D5. This will guarantee Bob a tie. 8 | -------------------------------------------------------------------------------- /2016_RoundC/evaluation.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | T=int(raw_input()) 3 | 4 | for tt in range(1,T+1): 5 | N=int(raw_input()) 6 | children=defaultdict(set) 7 | parent=defaultdict(set) 8 | names=set() 9 | for i in range(N): 10 | current,exp=raw_input().split("=") 11 | names.add(current) 12 | values=[t for t in exp.replace("(","#").replace(")","#").split("#")[1].split(",")] 13 | 14 | for val in values: 15 | children[val].add(current) 16 | parent[current].add(val) 17 | names.add(val) 18 | 19 | good=[] 20 | for name in parent: 21 | if len(parent[name])==1 and '' in parent[name]: 22 | good.append(name) 23 | 24 | arranged=set() 25 | while good: 26 | name=good.pop() 27 | arranged.add(name) 28 | for child in children[name]: 29 | if child in parent: 30 | parent[child].discard(name) 31 | if len(parent[child])==0: 32 | good.append(child) 33 | del parent[child] 34 | 35 | if len(names)==len(arranged)+1: #+1 for '' 36 | print "Case #"+str(tt)+": GOOD" 37 | else: 38 | print "Case #"+str(tt)+": BAD" -------------------------------------------------------------------------------- /2016_RoundC/monsterPath.py: -------------------------------------------------------------------------------- 1 | from collections import Counter 2 | T=int(raw_input()) 3 | R,C,P,Q=[None for x in range(4)] 4 | 5 | def dfs(grid, x,y, S, seen): 6 | global R,C,P,Q 7 | if S==0: 8 | return 0 9 | if x<0 or x>=R or y<0 or y>=C: 10 | return 0 11 | 12 | seen[x,y]+=1 13 | ans=max(dfs(grid,x+1,y,S-1,seen),dfs(grid,x-1,y,S-1,seen), 14 | dfs(grid,x,y+1,S-1,seen),dfs(grid,x,y-1,S-1,seen)) 15 | seen[x,y]-=1 16 | 17 | if grid[x][y]=="A": 18 | ans+=((1-P)**seen[x,y])*P 19 | else: 20 | ans+=((1-Q)**seen[x,y])*Q 21 | 22 | return ans 23 | 24 | for tt in range(1,T+1): 25 | R,C,RS,CS,S=[int(t) for t in raw_input().split()] 26 | P,Q=[float(t) for t in raw_input().split()] 27 | 28 | grid=[] 29 | for i in range(R): 30 | grid.append(raw_input().split()) 31 | seen=Counter() 32 | result=max(dfs(grid,RS+1,CS,S,seen),dfs(grid,RS-1,CS,S,seen), 33 | dfs(grid,RS,CS+1,S,seen),dfs(grid,RS,CS-1,S,seen)) 34 | 35 | print "Case #"+str(tt)+": %.7f" %(result) 36 | -------------------------------------------------------------------------------- /2016_RoundC/safeSquares.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | 18 | int main(){ 19 | int T; 20 | cin>>T; 21 | int R,C,K; 22 | int Ri,Ci; 23 | 24 | for(int tt=1;tt>R>>C>>K; 26 | vector> grid(R,vector(C,0)); 27 | for(int i=0;i>Ri>>Ci; 29 | grid[Ri][Ci]=1; 30 | } 31 | vector> maxL(R,vector(C,0)); 32 | long long result=0; 33 | for(int i=0;i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | int N; 18 | int A,D; 19 | int maxA,maxD; 20 | 21 | bool compute(){ 22 | cin>>N; 23 | unordered_map> lookup; 24 | for(int i=0;i>A>>D; 26 | lookup[i]=make_pair(A,D); 27 | } 28 | while(!lookup.empty()){ 29 | maxA=0; 30 | maxD=0; 31 | for(auto x:lookup){ 32 | maxA=max(maxA,x.second.first); 33 | maxD=max(maxD,x.second.second); 34 | } 35 | vector bad; 36 | for(auto x:lookup){ 37 | if(x.second.first==maxA && x.second.second==maxD){ 38 | return true; 39 | } 40 | if(x.second.first==maxA){bad.push_back(x.first);} 41 | if(x.second.second==maxD){bad.push_back(x.first);} 42 | } 43 | for(int y:bad){lookup.erase(y);} 44 | } 45 | return false; 46 | } 47 | 48 | int main(){ 49 | int T; 50 | cin>>T; 51 | 52 | for(int tt=1;tt 4 | XX.XX.XX.XX. and so on
5 | .XX.XX.XX.XX and so on
6 | X.XX.XX.XX.X and so on
7 | 8 | codejamonCipher.cpp: dp, the key optimization comes from the fact that each vocab word's length<=20. 9 | 10 | stretchRope.cpp: knapsack dp. dp\[L]=min(dp\[L],dp\[L-B]...dp\[L-A]). Remember to properly initialize everything. 11 | -------------------------------------------------------------------------------- /2016_RoundD/codejamonCipher.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | long long mod=1e9+7; 18 | 19 | struct node{ 20 | vector dict; 21 | node(const vector & some){ 22 | dict=some; 23 | } 24 | 25 | bool operator==(const node & d) const{ 26 | return dict==d.dict; 27 | } 28 | }; 29 | 30 | namespace std{ 31 | template<> 32 | struct hash{ 33 | size_t operator()(const node & d) const{ 34 | auto ic=hash(); 35 | size_t uniqueKey=0; 36 | for(int x:d.dict){ 37 | uniqueKey=(uniqueKey<<1) ^ (ic(x)); 38 | } 39 | return uniqueKey; 40 | } 41 | }; 42 | } 43 | 44 | int main(){ 45 | ios_base::sync_with_stdio(false); 46 | cin.tie(NULL); 47 | int T; 48 | cin>>T; 49 | int V,S; 50 | string word; 51 | 52 | for(int tt=1;tt>V>>S; 54 | unordered_map vocab; 55 | for(int i=0;i>word; 57 | vector a(26,0); 58 | for(char c:word){a[c-'a']++;} 59 | vocab[node(a)]++; 60 | } 61 | cout<<"Case #"<>word; 65 | l=word.size(); 66 | vectordp(l+1,0); 67 | dp[0]=1; 68 | for(int i=0;i v1(26,0); 70 | for(int w=1;w<=min(20,l-i);++w){ 71 | v1[word[i+w-1]-'a']++; 72 | node v2(v1); 73 | if(vocab.find(v2)!=vocab.end()){dp[i+w]=(dp[i+w]+dp[i]*vocab[v2]%mod)%mod;} 74 | } 75 | } 76 | cout<<" "< 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | long long bound=1e12; 18 | 19 | struct comp{ 20 | bool operator()(const pair & a, const pair & b){ 21 | return a.first>b.first; 22 | } 23 | }; 24 | 25 | int main(){ 26 | int T; 27 | cin>>T; 28 | int N,M,L; 29 | int A,B,P; 30 | 31 | for(int tt=1;tt>N>>M>>L; 33 | vectordp(L+1,bound); 34 | dp[0]=0; 35 | cin>>A>>B>>P; 36 | for(int i=A;i<=min(L,B);++i){dp[i]=P;} 37 | for(int i=1;i>A>>B>>P; 39 | priority_queue, vector>, comp> q; 40 | unordered_set invalid; 41 | for(int j=L-A;j>=max(L-B,0);j--){ 42 | if(dp[j]!=bound){q.push({dp[j],j});} 43 | } 44 | while(!q.empty() && invalid.find(q.top().second)!=invalid.end()){ 45 | q.pop(); 46 | } 47 | if(!q.empty()){ 48 | if(q.top().first+P<=M){ 49 | dp[L]=min(q.top().first+P,dp[L]); 50 | } 51 | } 52 | for(int j=L-1;j>=0;--j){ 53 | if(j-B>=0 && dp[j-B]!=bound){ 54 | q.push({dp[j-B],j-B}); 55 | } 56 | if(j+1-A>=0){invalid.insert(j+1-A);} 57 | while(!q.empty() && invalid.find(q.top().second)!=invalid.end()){q.pop();} 58 | if(!q.empty()){ 59 | if(q.top().first+P<=M){dp[j]=min(q.top().first+P,dp[j]);} 60 | } 61 | } 62 | } 63 | if(dp[L]>M){cout<<"Case #"< 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | 18 | int main(){ 19 | int T; 20 | cin>>T; 21 | int N,M; 22 | 23 | for(int tt=1;tt>N>>M; 25 | vector> dp(N+M+1,vector(N+1,0)); 26 | dp[1][1]=(double)(N)/(N+M); 27 | for(int i=2;i<=N+M;++i){ 28 | for(int j=i/2+1;j<=min(i,N);++j){ //j-1 issue 29 | dp[i][j]=dp[i-1][j-1]*(N-j+1)/(N+M-i+1); 30 | if(j!=i){dp[i][j]+=dp[i-1][j]*(M-i+1+j)/(N+M-i+1);} 31 | } 32 | } 33 | 34 | cout.precision(8); 35 | cout<<"Case #"<0: 6 | if (p & 1): 7 | ans*=base 8 | p/=2 9 | base=base*base 10 | return ans 11 | 12 | for tt in range(1,T+1): 13 | A=int(raw_input()) 14 | result=A-1 15 | for N in range(2,65): 16 | low=2 17 | high=A 18 | while low0: 22 | high=mid 23 | elif cal<0: 24 | low=mid+1 25 | else: 26 | result=min(result,mid) 27 | break 28 | print "Case #"+str(tt)+": "+str(result) -------------------------------------------------------------------------------- /2016_RoundE/diwaliLightings.py: -------------------------------------------------------------------------------- 1 | from collections import Counter 2 | T=int(raw_input()) 3 | 4 | for tt in range(1,T+1): 5 | S=raw_input() 6 | I,J=[int(t) for t in raw_input().split()] 7 | l=len(S) 8 | g1,r1=(I-1)/l,(I-1)%l 9 | g2,r2=(J-1)/l,(J-1)%l 10 | allDict=Counter(S) 11 | dict1=Counter(S[r1:]) 12 | dict2=Counter(S[:r2+1]) 13 | result=0 14 | if g1==g2: 15 | result=dict2["B"]-Counter(S[:r1])["B"] 16 | else: 17 | result+=dict1["B"]+allDict["B"]*(g2-g1-1)+dict2["B"] 18 | 19 | print "Case #"+str(tt)+": "+str(result) -------------------------------------------------------------------------------- /2016_RoundE/helper.py: -------------------------------------------------------------------------------- 1 | print 120 2 | seq=1 3 | 4 | def helper(startIndex,A): 5 | global seq 6 | if startIndex==4: 7 | C=[str(t) for t in A] 8 | print "5 2" #or "5 3" for large dataset 9 | print " ".join(C) 10 | seq+=1 11 | return 12 | for i in range(startIndex,5): 13 | A[i],A[startIndex]=A[startIndex],A[i] 14 | helper(startIndex+1,A) 15 | A[i],A[startIndex]=A[startIndex],A[i] 16 | 17 | B=[1,2,3,4,5] 18 | helper(0,B) -------------------------------------------------------------------------------- /2016_RoundE/partitioningNumber.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | 18 | int main(){ 19 | int T; 20 | cin>>T; 21 | int N,D; 22 | 23 | for(int tt=1;tt>N>>D; 25 | long long result=0; 26 | for(int l=1;l<=N/D;l++){ 27 | if(N%l==0 && (N/l)%D==0){result++;} 28 | 29 | for(int A=max(D,(N-1)/l+1-2);A<=N/l;A++){ 30 | if(A==0 || A%D!=0){continue;} 31 | int remainder=N-A*l; 32 | if(remainder%2==0){ 33 | int n3=remainder/2; 34 | if(n3>0 && n30 && remainder=3){ 45 | for(int A=(N-1)/l+1-2;A<=N/l;++A){ 46 | if(A==0 || A%D!=0){continue;} 47 | int remainder=N-A*(l-2)-(A+1+A+2); 48 | int n1=max(1,l-2-remainder); 49 | int n2=l-2-(remainder+1)/2; 50 | if(n2>=n1){result+=n2-n1+1;} 51 | } 52 | } 53 | 54 | 55 | } 56 | cout<<"Case #"< 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | int N; 16 | double X[10001]; 17 | double Y[10001]; 18 | double W[10001]; 19 | const double eps=1e-7; 20 | 21 | double weight(double x, double y){ 22 | double answer=0; 23 | for(int i=1;i<=N;++i){ 24 | answer+=max(fabs(x-X[i]),fabs(y-Y[i]))*W[i]; 25 | } 26 | return answer; 27 | } 28 | 29 | double compute(double x){ 30 | double low=-1000; 31 | double high=1000; 32 | while(high-low>eps){ 33 | double p1=low+(high-low)/3; 34 | double p2=low+(high-low)*2/3; 35 | if(weight(x,p1)>T; 45 | for(int tt=1;tt>N; 47 | for(int j=1;j<=N;++j){ 48 | cin>>X[j]; 49 | cin>>Y[j]; 50 | cin>>W[j]; 51 | } 52 | double low=-1000; 53 | double high=1000; 54 | while(high-low>eps){ 55 | double p1=low+(high-low)/3; 56 | double p2=low+(high-low)*2/3; 57 | if(compute(p1) 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | long long P[10001]; 16 | int numbers[10001]; 17 | 18 | int main(){ 19 | int T; 20 | cin>>T; 21 | long long mod=1e9+7; 22 | P[0]=1; 23 | for(int i=1;i<=10000;++i){ 24 | P[i]=P[i-1]*2%mod; 25 | } 26 | for(int tt=1;tt>N; 29 | for(int j=1;j<=N;++j){ 30 | cin>>numbers[j]; 31 | } 32 | long long result=0; 33 | for(int j=1;j<=N;++j){ 34 | for(int k=j+1;k<=N;++k){ 35 | result=(result+(numbers[k]-numbers[j])*P[k-j-1])%mod; 36 | } 37 | } 38 | cout<<"Case #"<1: 13 | line=raw_input() 14 | for i in range(Q): 15 | F2[i]=line[i] 16 | 17 | my=raw_input() 18 | One=0 19 | Two=0 20 | Three=0 21 | Four=0 22 | for i in range(Q): 23 | if my[i]==F1[i]: 24 | if my[i]==F2[i]: 25 | One+=1 26 | else: 27 | Two+=1 28 | else: 29 | if my[i]==F2[i]: 30 | Three+=1 31 | else: 32 | Four+=1 33 | 34 | s1=0 35 | s2=0 36 | score=[int(t) for t in raw_input().split()] 37 | if N>1: 38 | s1,s2=score 39 | else: 40 | s1=score[0] 41 | 42 | result=0 43 | for a in range(One+1): 44 | for b in range(Two+1): 45 | for c in range(Three+1): 46 | for d in range(Four+1): 47 | p1=a+b+Three-c+Four-d 48 | if p1!=s1: 49 | continue 50 | if N>1: 51 | p2=a+Two-b+c+Four-d 52 | if p2!=s2: 53 | continue 54 | result=max(result,a+b+c+d) 55 | 56 | print "Case #"+str(tt)+": "+str(result) 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /2017_RoundD/README.md: -------------------------------------------------------------------------------- 1 | sightSeeing.cpp: dp\[i]\[j] is the earliest time to arrive at i after sightseeing j cities. I used long long for everything just to be safe. 2 | 3 | sherlockAndTheMatrixGame.cpp: This is a N^2 log K solution. The memory constraints do not allow a segment tree implementation. A worst case N^2 log range log N solution (uses multiset to generate the largest K prefix sums) passes the large dataset. Even though this implementation does not pass the large dataset, its worst case time complexity is better. 4 | -------------------------------------------------------------------------------- /2017_RoundD/sightSeeing.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | long long dp[2001][2001]; 16 | long long bound=1e9+1; 17 | 18 | int main(){ 19 | int T; 20 | cin>>T; 21 | for(int tt=1;tt>N>>Ts>>Tf; 24 | long long Si,Fi,Di; 25 | cin>>Si>>Fi>>Di; 26 | for(int i=0;i<=2000;++i){ 27 | for(int j=0;j<=2000;++j){ 28 | dp[i][j]=bound; 29 | } 30 | } 31 | dp[1][0]=0; 32 | for(int i=2;i<=N;++i){ 33 | for(int j=0;j<=i-1;++j){//j==0 34 | long long potential; 35 | if(j>0){ 36 | potential=dp[i-1][j-1]+Ts; 37 | if(potential<=Si){dp[i][j]=min(dp[i][j],Si+Di);} 38 | else{ 39 | dp[i][j]=min(dp[i][j], ((potential-Si-1)/Fi+1)*Fi+Si+Di ); //might become negative? 40 | } 41 | } 42 | 43 | potential=dp[i-1][j]; //don't go sightseeing 44 | 45 | if(potential<=Si){dp[i][j]=min(dp[i][j],Si+Di);} 46 | else{ 47 | dp[i][j]=min(dp[i][j], ((potential-Si-1)/Fi+1)*Fi+Si+Di ); 48 | } 49 | 50 | } 51 | if(i==N){break;} 52 | cin>>Si>>Fi>>Di; 53 | 54 | } 55 | int result=-1; 56 | for(int r=0;r<=N-1;++r){ 57 | if(dp[N][r]<=Tf){result=r;} 58 | } 59 | if(result<0){cout<<"Case #"< 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | 16 | int main(){ 17 | int T; 18 | cin>>T; 19 | for(int tt=1;tt>x[i]; 27 | Xmin=min(Xmin,x[i]); 28 | Xmax=max(Xmax,x[i]); 29 | cin>>y[i]; 30 | cin>>z[i]; 31 | } 32 | double result=(double)(Xmax-Xmin)/6; 33 | 34 | cout.precision(10); 35 | cout<<"Case #"< 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | using namespace std; 14 | 15 | int main(){ 16 | int dp[10001]; 17 | for(int i=0;i<=10000;++i){dp[i]=10002;} 18 | dp[0]=0; 19 | for(int i=1;i<=10000;++i){ 20 | double y=sqrt(i); 21 | if ((y-floor(y))==0){ 22 | dp[i]=1; 23 | continue; 24 | } 25 | for(int j=1;j<=100;++j){ 26 | if(j*j>i){ 27 | break; 28 | } 29 | dp[i]=min(dp[i],1+dp[i-j*j]); 30 | } 31 | } 32 | int T; 33 | cin>>T; 34 | for(int tt=1;tt>N; 37 | 38 | cout<<"Case #"< 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | 16 | typedef pair pi; 17 | 18 | int main(){ 19 | int T; 20 | cin>>T; 21 | for(int tt=1;tt>E>>N; 24 | int H=0; 25 | priority_queue,greater> small; 26 | priority_queue>big; 27 | unordered_set invalid; 28 | for(int i=0;i>Si; 31 | small.push(make_pair(Si,i)); 32 | big.push({Si,i}); 33 | } 34 | while(true){ 35 | while(!small.empty() && invalid.find(small.top().second)!=invalid.end()){ 36 | small.pop(); 37 | } 38 | while(!small.empty() && E>small.top().first){ 39 | E-=small.top().first; 40 | invalid.insert(small.top().second); 41 | small.pop(); 42 | H++; 43 | N--; 44 | } 45 | while(!big.empty() && invalid.find(big.top().second)!=invalid.end()){ 46 | big.pop(); 47 | } 48 | if(H>0 && N>1){ 49 | E+=big.top().first; 50 | H--; 51 | invalid.insert(big.top().second); 52 | big.pop(); 53 | N--; 54 | } 55 | else{break;} 56 | } 57 | 58 | cout<<"Case #"< 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | using namespace std; 14 | vector numbers(10000); 15 | vector seq(10000); 16 | 17 | int main(){ 18 | int T; 19 | cin>>T; 20 | for(int tt=1;tt>N; 23 | for(int i=0;i>numbers[i]; 25 | seq[i]=numbers[i]; 26 | } 27 | sort(seq.begin(),seq.begin()+N); 28 | int left=0; 29 | int right=N-1; 30 | 31 | string result="NO"; 32 | int E=N; 33 | while(E>1){ 34 | int pivot=floor((E-1)/2); 35 | //cout<<"pivot is "<10**5: 11 | break 12 | factDict[j]=fact 13 | j+=1 14 | 15 | for m in range(1,T+1): 16 | A,N,P=raw_input().split() 17 | A,N,P=int(A),int(N),int(P) 18 | remainderDict=defaultdict() 19 | bound=factDict[N] 20 | 21 | currentVal=A%P 22 | seq=1 23 | 24 | while currentVal not in remainderDict: 25 | remainderDict[currentVal]=seq 26 | seq+=1 27 | bound-=1 28 | if bound==0: 29 | break 30 | currentVal=(currentVal*A)%P 31 | 32 | result=1 33 | if bound==0: 34 | result=currentVal 35 | else: 36 | offset=remainderDict[currentVal]-1 37 | period=seq-remainderDict[currentVal] 38 | small=1 39 | for t in range(1,N+1): 40 | small=(small*t)%period #small could be 0 in this case 41 | 42 | small=small+(period-offset)%period 43 | #handle the case of small==0 44 | if small==0: 45 | small=period 46 | for t in range(small-1): 47 | currentVal=(currentVal*A)%P 48 | result=currentVal 49 | print "Case #"+str(m)+": "+str(result) 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /2017_RoundG/matrixCutting.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | int small[40][40][40][40]; 16 | long long dp[40][40][40][40]; 17 | 18 | long long helper(int i,int j, int s, int t){ 19 | if(dp[i][j][s][t]!=0){ 20 | return dp[i][j][s][t]; 21 | } 22 | if(i==s && j==t){ 23 | return 0; 24 | } 25 | long long maxCoins=0; 26 | for(int h=i;h>T; 39 | for(int tt=1;tt>N>>M; 42 | int grid[N][M]; 43 | for(int i=0;i>grid[i][j]; 46 | } 47 | } 48 | memset(small,0,sizeof small); 49 | for(int i=0;i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | using namespace std; 14 | const int bound=2e4+2; 15 | 16 | double sums[bound]; 17 | 18 | int main(){ 19 | int T; 20 | cin>>T; 21 | for(int tt=1;tt>N>>K; 24 | memset(sums,0,sizeof sums); 25 | vector V(N); 26 | for(int i=0;i>V[i]; 28 | } 29 | sort(V.begin(),V.end()); 30 | double currentSum=0; 31 | for(int i=N-1;i>=0;i--){ 32 | currentSum+=V[i]; 33 | sums[i]=currentSum; 34 | } 35 | double base=sums[0]/N; 36 | for(int i=1;i<=K;++i){ 37 | int pos=lower_bound(V.begin(),V.end(),base)-V.begin(); //can't be end 38 | base=(base*(pos)+sums[pos])/N; 39 | } 40 | cout.precision(6); 41 | cout<<"Case #"< 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | using namespace std; 14 | int N; 15 | 16 | int dfs(int state,int startIndex,vector& edges,vector>& grid, 17 | int maxSide, int sideSum){ 18 | int answer=0; 19 | if(startIndex==N){return answer;} 20 | if(edges.size()>=3 && 2*maxSide es=edges; 34 | es.push_back(grid[j][k]); 35 | int mSide=max(maxSide,grid[j][k]); 36 | int sSum=sideSum+grid[j][k]; 37 | answer+=dfs(s, j+1,es,grid,mSide,sSum); 38 | } 39 | } 40 | //cout<<"state is "<>T; 47 | for(int tt=1;tt>N; 49 | vector>grid; 50 | for(int i=0;i line(N); 52 | for(int j=0;j>line[j]; 54 | } 55 | grid.push_back(line); 56 | 57 | } 58 | int state[1<sides; 65 | result+=dfs(i,0,sides,grid,0,0); 66 | } 67 | cout<<"Case #"< 2 | 3 | using namespace std; 4 | const long long mod=1e9+7; 5 | 6 | long long p(long long i, int K){ 7 | long long answer=1; 8 | for(int j=K;j>0;j>>=1){ 9 | if(j &1){ 10 | answer=answer*i%mod; 11 | } 12 | i=i*i%mod; 13 | } 14 | return answer; 15 | } 16 | 17 | int main(){ 18 | int T; 19 | cin>>T; 20 | for(int tt=1;tt>N>>K>>X1>>Y1>>C>>D>>E1>>E2>>F; 24 | long long A[N+1]; 25 | A[1]=(X1+Y1)%F; 26 | for(int i=2;i=(N+1)/2: 39 | best[j]=N-best[j] 40 | for i in range(P-1,0,-1): 41 | best[i]=best[i]+best[i+1] 42 | dummy=node() 43 | for i in range(M): 44 | s=raw_input() 45 | it=dummy 46 | for c in s: 47 | it=it.children[c] 48 | result=compute(dummy,best,0,ones,N,P) 49 | print "Case #"+str(tt)+": "+str(result) 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /2018_RoundE/yogurt.py: -------------------------------------------------------------------------------- 1 | 2 | T=raw_input() 3 | T=int(T) 4 | 5 | for tt in range(1,T+1): 6 | N,K=raw_input().split() 7 | N,K=int(N),int(K) 8 | result=0 9 | y=[-int(t) for t in raw_input().split()] 10 | y.sort() 11 | #print y 12 | days=0 13 | belly=K 14 | while y: 15 | potential=-y.pop() 16 | if potential<=days: 17 | continue 18 | result+=1 19 | belly-=1 20 | if belly==0: 21 | belly=K 22 | days+=1 23 | 24 | print "Case #"+str(tt)+": "+str(result) 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /2018_RoundF/README.md: -------------------------------------------------------------------------------- 1 | specializingVillages.py: The official analysis suggested we sort the edges based on weight, but that is at least O (E log E) complexity, and in my honest opinion that approach is not optimal. My approach is somewhat different: Since all edges have different values, if we select the smallest outgoing edge from each vertex, we would get a spanning forest (We cannot have a loop because all edges have different value, and a loop would contradict the strictly greater than relationship). The number of ways would be pow(2, number of spanning forest). Notice a special case here: if we have an edge with weight 0, with two endpoints spa and spb, then the neighbors of spa and spb can also be viewed as spanning components. Thus in the exponential part we add (number of neighbors of spa and spb)-2. The final answer would be pow(2, number of spanning forest + number of neighbors of spa and spb - 2 ) 2 | 3 | palindromicSequence.py: My solution is very solid and passes all test cases, including my own hand made test cases. Most other solutions online fail test cases such as "2 3 8", "2 5 17" etc. I have also wrote helper.cpp to help you visualize the sequence when N is small. 4 | -------------------------------------------------------------------------------- /2018_RoundF/commonAnagrams.py: -------------------------------------------------------------------------------- 1 | 2 | T=raw_input() 3 | T=int(T) 4 | 5 | for tt in range(1,T+1): 6 | L=raw_input() 7 | L=int(L) 8 | a=raw_input() 9 | b=raw_input() 10 | lookup=set() 11 | result=0 12 | for i in range(L): 13 | val=[0 for x in range(26)] 14 | for j in range(i,L): 15 | val[ord(b[j])-ord('A')]+=1 16 | lookup.add(tuple(val)) 17 | #print lookup 18 | for i in range(L): 19 | val=[0 for x in range(26)] 20 | for j in range(i,L): 21 | val[ord(a[j])-ord('A')]+=1 22 | if tuple(val) in lookup: 23 | result+=1 24 | 25 | print "Case #"+str(tt)+": "+str(result) 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /2018_RoundF/helper.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | int main(){ 11 | int T; 12 | cin>>T; 13 | for(int tt=1;tt>L>>N>>K; 16 | long long result=0; 17 | vector> dict(N+1); 18 | vectorfinal; 19 | if(N>0){ 20 | for(int off=0;off1){ 28 | for(int off=0;off=r: 23 | if isPalindrome(prefix,r-l,l-1): 24 | count+=1 25 | else: 26 | count+=choices**((r-2*l+1)/2) 27 | return count 28 | 29 | for tt in range(1,T+1): 30 | L,N,K=raw_input().split() 31 | L,N,K=int(L),int(N),int(K) 32 | result=0 33 | if K<=N: 34 | print "Case #"+str(tt)+": "+str(K) 35 | continue 36 | if L==1: 37 | print "Case #"+str(tt)+": "+"0" 38 | continue 39 | start=max(0,int((N+1)/2-math.log(K,L))) #precision of float or double might be a problem, debug took so long 40 | remainder=K-2*start 41 | 42 | if remainder==0: 43 | print "Case #"+str(tt)+": "+str(2*start) 44 | continue 45 | prefix="" 46 | done=False 47 | while remainder and not done: 48 | for off in range(L+1): 49 | if off==L: 50 | result=0 51 | done=True 52 | break 53 | c=chr(ord('a')+off) 54 | if isPalindrome(prefix+c): 55 | if remainder==1: 56 | result=2*start+len(prefix)+1 57 | done=True 58 | break 59 | remainder-=1 60 | kid=compute(len(prefix)+1,prefix+c,N-2*start,L) 61 | if remainder>kid: 62 | remainder-=kid 63 | else: #if kid>=remainder 64 | prefix+=c 65 | break 66 | print "Case #"+str(tt)+": "+str(result) 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /2018_RoundF/specializingVillages.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | T=raw_input() 3 | T=int(T) 4 | mod=10**5+1 5 | for tt in range(1,T+1): 6 | V,E=raw_input().split() 7 | V,E=int(V),int(E) 8 | minDist=[mod for i in range(V+1)] 9 | minNeighbor=[0 for i in range(V+1)] 10 | spa,spb=0,0 11 | for i in range(E): 12 | a,b,dist=raw_input().split() 13 | a,b,dist=int(a),int(b),int(dist) 14 | if dist==0: 15 | spa=a 16 | spb=b 17 | if dist 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main(){ 8 | int T; 9 | cin>>T; 10 | for(int tt=1;tt>N; 13 | vectornumbers; 14 | for(int i=0;i>j; 17 | numbers.push_back(j); 18 | } 19 | sort(numbers.begin(),numbers.end()); 20 | long long result=0; 21 | long long start=0; 22 | while(start=3){ 27 | result+=(start*(start-1)*(start-2))/6; 28 | } 29 | if(start>=2 && N-start>=1){ 30 | result+=start*(start-1)/2*(N-start); 31 | } 32 | for(int i=start;ik){ 39 | result=result+it-k; 40 | //cout<<"i "<numbers[k]){ 45 | k++; 46 | } 47 | if(k 2 | 3 | using namespace std; 4 | const int mod=1e9+7; 5 | 6 | int main(){ 7 | int T; 8 | cin>>T; 9 | for(int tt=1;tt>N>>M; 12 | long long p[M+1]; 13 | p[0]=1; 14 | for (int i=1;i=0;k--){ 35 | nPart[k]=nPart[k+1]*it%mod*right%mod; 36 | //cout<<"nPart "<0 and count%2==1: 28 | badCount+=1 29 | #print str(start)+" "+str(end)+" "+str(badCount) 30 | if badCount<2: 31 | result+=1 32 | 33 | 34 | print "Case #"+str(tt)+": "+str(result) 35 | 36 | 37 | -------------------------------------------------------------------------------- /2019_RoundB/energyStones.py: -------------------------------------------------------------------------------- 1 | 2 | T=raw_input() 3 | T=int(T) 4 | 5 | for tt in range(1,T+1): 6 | N=raw_input() 7 | N=int(N) 8 | A=[] 9 | B=[] 10 | total=0 11 | for i in range(N): 12 | S,E,L=raw_input().split() 13 | S,E,L=int(S),int(E),int(L) 14 | total+=S 15 | if L==0: 16 | B.append(E) 17 | else: 18 | A.append([S,E,L]) 19 | A.sort(key=lambda x:float(x[0])/x[2]) 20 | C=len(A) 21 | dp=[[0 for y in range(total+1)] for x in range(C)] 22 | if C>0: 23 | dp[0][A[0][0]]=A[0][1] 24 | for i in range(1,C): 25 | for j in range(total+1): 26 | dp[i][j]=max(dp[i][j],dp[i-1][j]) 27 | if j>=A[i][0]: 28 | penalty=j-A[i][0] 29 | remainder=A[i][1]-penalty*A[i][2] 30 | if remainder<=0: 31 | continue 32 | dp[i][j]=max(dp[i][j],dp[i-1][penalty]+remainder) 33 | result=0 34 | if C>0: 35 | for t in range(total+1): 36 | result=max(result,dp[C-1][t]) 37 | for good in B: 38 | result+=good 39 | 40 | print "Case #"+str(tt)+": "+str(result) 41 | 42 | 43 | -------------------------------------------------------------------------------- /2019_RoundC/README.md: -------------------------------------------------------------------------------- 1 | wiggleWalk.py has the best time complexity you can achieve, strictly O(N). 2 | 3 | My approach in circuitBoard.py: first use heap to record the maximum length of consecutive good cells starting from each position. After that we use the histogram approach (https://leetcode.com/problems/largest-rectangle-in-histogram/) to find max area. 4 | 5 | problem 3 is a knapsack problem. The thing to notice is that we cannot assume dog positions are given in ascending order, thus we need to sort! 6 | -------------------------------------------------------------------------------- /2019_RoundC/catchSome.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | import sys 3 | T=raw_input() 4 | T=int(T) 5 | 6 | for tt in range(1,T+1): 7 | N,K=raw_input().split() 8 | N,K=int(N),int(K) 9 | 10 | pos=[int(t) for t in raw_input().split()] 11 | color=defaultdict(list) 12 | colors=[int(t) for t in raw_input().split()] 13 | same=[] 14 | for i in range(len(colors)): 15 | color[colors[i]].append(pos[i]) 16 | for c in color: 17 | same.append(sorted(color[c])) 18 | #print same 19 | 20 | C=len(same) 21 | dp=[[[sys.maxint for z in range(2)] for j in range(K+1)] for x in range(C)] 22 | dp[0][0][0]=0 23 | dp[0][0][1]=0 24 | for j in range(1,min(len(same[0])+1,K+1)): 25 | dp[0][j][0]=same[0][j-1]*2 26 | dp[0][j][1]=same[0][j-1] 27 | for i in range(1,C): 28 | for j in range( K+1 ): 29 | for t in range(min(j+1,len(same[i])+1)): 30 | if t==0: 31 | dp[i][j][0]=min(dp[i][j][0],dp[i-1][j][0]) 32 | dp[i][j][1]=min(dp[i][j][1],dp[i-1][j][1]) 33 | else: 34 | dp[i][j][0]=min(dp[i][j][0], 2*same[i][t-1]+dp[i-1][j-t][0]) 35 | dp[i][j][1]=min(dp[i][j][1], 2*same[i][t-1]+dp[i-1][j-t][1]) 36 | dp[i][j][1]=min(dp[i][j][1], same[i][t-1]+dp[i-1][j-t][0]) 37 | 38 | print "Case #"+str(tt)+": "+str(dp[C-1][K][1]) 39 | 40 | 41 | -------------------------------------------------------------------------------- /2019_RoundC/circuitBoard.py: -------------------------------------------------------------------------------- 1 | 2 | import heapq 3 | T=raw_input() 4 | T=int(T) 5 | 6 | for tt in range(1,T+1): 7 | R,C,K=raw_input().split() 8 | R,C,K=int(R),int(C),int(K) 9 | hist=[[0 for y in range(C)] for x in range(R)] 10 | for i in range(R): 11 | row=[int(t) for t in raw_input().split()] 12 | left=0 13 | right=1 14 | minH=[[row[0],0]] 15 | maxH=[[-row[0],0]] 16 | invalid=set() 17 | while rightK: 22 | hist[i][left]=right-1-left+1 23 | old=row[left] 24 | invalid.add(left) 25 | while maxH[0][1] in invalid: 26 | heapq.heappop(maxH) 27 | while minH[0][1] in invalid: 28 | heapq.heappop(minH) 29 | left+=1 30 | 31 | right+=1 32 | for t in range(left,len(row)): 33 | hist[i][t]=len(row)-1-t+1 34 | 35 | #print hist 36 | area=0 37 | for j in range(C): 38 | s=[] 39 | for i in range(R): 40 | if not s or hist[i][j]>=hist[s[-1]][j]: 41 | s.append(i) 42 | else: 43 | while s and hist[s[-1]][j]>hist[i][j]: 44 | pivot=s.pop() 45 | if not s: #how could i mess up indentation 46 | area=max(area,hist[pivot][j]*(i)) 47 | else: 48 | area=max(area,hist[pivot][j]*(i-s[-1]-1)) 49 | s.append(i) 50 | while s: 51 | pivot=s.pop() 52 | if not s: 53 | area=max(area,hist[pivot][j]*(R)) 54 | else: 55 | area=max(area,hist[pivot][j]*(R-s[-1]-1)) 56 | 57 | 58 | print "Case #"+str(tt)+": "+str(area) 59 | 60 | 61 | -------------------------------------------------------------------------------- /2019_RoundC/wiggleWalk.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | T=raw_input() 3 | T=int(T) 4 | 5 | for tt in range(1,T+1): 6 | N,R,C,startR,startC=raw_input().split() 7 | N,R,C,startR,startC=int(N),int(R),int(C),int(startR),int(startC) 8 | colDict=defaultdict(lambda:defaultdict(lambda:0)) 9 | rowDict=defaultdict(lambda:defaultdict(lambda:0)) 10 | x=startR 11 | y=startC 12 | 13 | order=raw_input() 14 | for c in range(len(order)): 15 | if order[c]=="E": 16 | newX=x 17 | if not colDict[x][y+1]: 18 | newY=y+1 19 | else: 20 | newY=y+colDict[x][y+1]+1 21 | elif order[c]=="W": 22 | newX=x 23 | if not colDict[x][y-1]: 24 | newY=y-1 25 | else: 26 | newY=y-colDict[x][y-1]-1 27 | elif order[c]=="N": 28 | newY=y 29 | if not rowDict[y][x-1]: 30 | newX=x-1 31 | else: 32 | newX=x-rowDict[y][x-1]-1 33 | else: 34 | newY=y 35 | if not rowDict[y][x+1]: 36 | newX=x+1 37 | else: 38 | newX=x+rowDict[y][x+1]+1 39 | leftBound=0 40 | if y>1: 41 | leftBound=colDict[x][y-1] 42 | rightBound=0 43 | if y1: 51 | upBound=rowDict[y][x-1] 52 | downBound=0 53 | if x0 and odds[index-1]==pos: 36 | if count%2==0: 37 | del odds[index-1] 38 | else: 39 | if count%2==1: 40 | odds.insert(index,pos) 41 | total^=numbers[pos] 42 | total^=val 43 | numbers[pos]=val 44 | 45 | ones=0 46 | for i in range(10): 47 | if (total & (1<=reqEat: 48 | result+="Y" 49 | else: 50 | result+="N" 51 | 52 | 53 | print "Case #"+str(caseNum)+": "+str(result) 54 | seq+=S+D+1 55 | caseNum+=1 56 | -------------------------------------------------------------------------------- /2019_RoundE/streetChecker.py: -------------------------------------------------------------------------------- 1 | import fileinput 2 | from bisect import bisect 3 | 4 | caseNum=1 5 | 6 | lines=[] 7 | for line in fileinput.input(): 8 | lines.append(line.rstrip()) 9 | 10 | maxR=1 11 | for seq in range(1,len(lines)): 12 | L,R=lines[seq].split() 13 | L,R=int(L),int(R) 14 | lines[seq]=[L,R] 15 | maxR=max(maxR,R) 16 | 17 | bound=int(maxR**0.5) 18 | A=[True for i in range(bound+1)] 19 | B=[] #primes including 2 20 | for x in range(2, bound+1): 21 | if not A[x]: 22 | continue 23 | else: 24 | B.append(x) 25 | it=x**2 26 | while it<=bound: 27 | A[it]=False 28 | it+=x 29 | 30 | def calc(low,high): 31 | if low>high: 32 | return 0 33 | A=[True for i in range(high-low+1)] 34 | count=0 35 | for p in B: 36 | s=(low/p)*p 37 | if s2: 46 | count+=1 47 | return count 48 | 49 | #print B 50 | 51 | for seq in range(1,len(lines)): 52 | L,R=lines[seq] 53 | result=0 #number is 1 54 | case1=0 55 | if 1>=L and 1<=R: 56 | case1+=1 57 | #case1+=A[R]-A[L-1] 58 | case1+=calc(L,R) 59 | L1=L 60 | while L1%4!=2: 61 | L1+=1 62 | case2=0 63 | if R>=L1: 64 | case2=(R-L1)/4+1 65 | case3=0 66 | if L<=4 and 4<=R: 67 | case3+=1 68 | L2=L 69 | while L2%4!=0: 70 | L2+=1 71 | R2=R 72 | while R2%4!=0: 73 | R2-=1 74 | if L2<=R2: 75 | L2/=4 76 | R2/=4 77 | case3+=calc(L2,R2) 78 | case4=0 79 | if 8>=L and 8<=R: 80 | case4+=1 81 | result=case1+case2+case3+case4 82 | 83 | #print str(case1)+" "+str(case2)+" "+str(case3)+" "+str(case4) 84 | print "Case #"+str(caseNum)+": "+str(result) 85 | caseNum+=1 86 | 87 | -------------------------------------------------------------------------------- /2019_RoundF/README.md: -------------------------------------------------------------------------------- 1 | villages.py will not meet time constraint due to the slowness of python, villages.cpp will pass all test cases. However, the underlying ideas behind and theories of villages.py and villages.cpp are the same. The key idea is to build the graph first, identify the relationship between parent and child node, and then apply dp. Here I used bfs instead of dfs because the recursion depth limit posed by python, but either bfs or dfs will work! 2 | -------------------------------------------------------------------------------- /2019_RoundF/flattening.py: -------------------------------------------------------------------------------- 1 | import fileinput 2 | import sys 3 | from collections import Counter 4 | 5 | seq=1 6 | caseNum=1 7 | 8 | lines=[] 9 | for line in fileinput.input(): 10 | lines.append(line.rstrip()) 11 | 12 | result=0 13 | 14 | while seqmaxCount: 28 | maxCount=lookup[numbers[j]] 29 | dp[i][j]=count-maxCount 30 | #print dp 31 | M=[[sys.maxint for j in range(K+1)]for i in range(N)] 32 | for s in range(K): 33 | M[0][s]=0 34 | for i in range(1,N): 35 | M[i][0]=dp[0][i] 36 | for j in range(1,K+1): 37 | for t in range(i): 38 | M[i][j]=min(M[i][j],M[t][j-1]+dp[t+1][i]) 39 | #print M 40 | print "Case #"+str(caseNum)+": "+str(M[N-1][K]) 41 | seq+=2 42 | caseNum+=1 43 | -------------------------------------------------------------------------------- /2019_RoundF/teachMe.py: -------------------------------------------------------------------------------- 1 | import fileinput 2 | from collections import Counter 3 | 4 | seq=1 5 | caseNum=1 6 | 7 | lines=[] 8 | for line in fileinput.input(): 9 | lines.append(line.rstrip()) 10 | 11 | result=0 12 | 13 | while seqM: 31 | print "Case #"+str(caseNum)+": "+str(-1) 32 | seq+=2 33 | caseNum+=1 34 | continue 35 | 36 | candidate=0 37 | for i in range(63,-1,-1): 38 | if numOnes[63-i]>=N-numOnes[63-i]: 39 | candidate=((1<=H: 26 | dp[aState]=1 27 | #print dp 28 | for i in range(N): 29 | for state in range((1<=72: 18 | numbers[i]=72+(numbers[i]&1) 19 | total+=numbers[i] 20 | if numbers[i]>9: 21 | bigNum+=1 22 | digitSum+=numbers[i]*(i+1) 23 | numbers.insert(0,0) 24 | 25 | if bigNum>1: 26 | print "Case #"+str(caseNum)+": "+"YES" 27 | caseNum+=1 28 | seq+=1 29 | continue 30 | 31 | digitSum%=11 32 | if digitSum%2==1: 33 | digitSum=(digitSum+11)/2 34 | else: 35 | digitSum=digitSum/2 36 | 37 | dp=[[0 for z in range(11)]for y in range(total/2+1)] 38 | 39 | for t in range(min(total/2+1,numbers[1]+1)): 40 | dp[t][t%11]=1 41 | for x in range(2,10): 42 | for y in range(total/2,-1,-1): 43 | for z in range(11): 44 | for count in range(min(numbers[x]+1,y+1)): 45 | currentMod=(count*x)%11 46 | if dp[y-count][(z-currentMod)%11]==1: 47 | dp[y][z]=1 48 | break 49 | 50 | #print dp 51 | result="NO" 52 | if dp[total/2][digitSum]: 53 | result="YES" 54 | print "Case #"+str(caseNum)+": "+result 55 | caseNum+=1 56 | 57 | -------------------------------------------------------------------------------- /2019_RoundH/h-index.py: -------------------------------------------------------------------------------- 1 | import fileinput 2 | import heapq 3 | 4 | lines=[] 5 | for line in fileinput.input(): 6 | lines.append(line.rstrip()) 7 | 8 | seq=1 9 | caseNum=1 10 | while seqh and q[0]>h: 22 | h+=1 23 | #print q 24 | result+=" "+str(h) 25 | print "Case #"+str(caseNum)+":"+result 26 | caseNum+=1 27 | seq+=2 -------------------------------------------------------------------------------- /2019_practiceRound/README.md: -------------------------------------------------------------------------------- 1 | mural.py: the overall effect is that we can take up to at most (N+1)/2 length of subarray, and greedily it is achievable. 2 | 3 | kickstartAlarm.cpp: Note that if you use modulus after the "+=" operator, the modulus can not take effect. e.g. A+=B%C, in this expression A is never modulus-ed by C and will grow big. 4 | -------------------------------------------------------------------------------- /2019_practiceRound/kickstartAlarm.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | const long long mod=1e9+7; 5 | 6 | long long p(long long i, int K){ 7 | long long answer=1; 8 | for(int j=K;j>0;j>>=1){ 9 | if(j &1){ 10 | answer=answer*i%mod; 11 | } 12 | i=i*i%mod; 13 | } 14 | return answer; 15 | } 16 | 17 | int main(){ 18 | int T; 19 | cin>>T; 20 | for(int tt=1;tt>N>>K>>X1>>Y1>>C>>D>>E1>>E2>>F; 24 | long long A[N+1]; 25 | A[1]=(X1+Y1)%F; 26 | for(int i=2;iK: 30 | low=mid+1 31 | else: 32 | high=mid 33 | 34 | #print low 35 | print "Case #"+str(caseNum)+": "+str(low) 36 | caseNum+=1 37 | 38 | seq+=2 39 | -------------------------------------------------------------------------------- /2020_RoundB/README.md: -------------------------------------------------------------------------------- 1 | For problem 4, solution p4 will pass test cases if pypy2 is used, and robot.cpp will pass all test cases no matter what. 2 | 3 | global ranking 562 in this contest 4 | -------------------------------------------------------------------------------- /2020_RoundB/p1.py: -------------------------------------------------------------------------------- 1 | import fileinput 2 | 3 | lines=[] 4 | for line in fileinput.input(): 5 | lines.append(line.rstrip()) 6 | 7 | seq=1 8 | caseNum=1 9 | 10 | while seqnumbers[i-1] and numbers[i]>numbers[i+1]: 18 | count+=1 19 | 20 | 21 | print "Case #"+str(caseNum)+": "+str(count) 22 | caseNum+=1 23 | seq+=2 -------------------------------------------------------------------------------- /2020_RoundB/p2.py: -------------------------------------------------------------------------------- 1 | import fileinput 2 | 3 | lines=[] 4 | for line in fileinput.input(): 5 | lines.append(line.rstrip()) 6 | 7 | seq=1 8 | caseNum=1 9 | 10 | while seq0 and y0: 36 | for t in range(1,x+1): 37 | steps=t-1+W-2 38 | result+=2**(factorial[steps]-factorial[steps-t+1]-factorial[t-1]-steps-1) 39 | 40 | x=D+1 41 | y=L-1 42 | while x0: 43 | steps=x-1+y-1 44 | result+=2**(factorial[steps]-factorial[steps-x+1]-factorial[x-1]-steps) 45 | x+=1 46 | y-=1 47 | if x==H and y>0: 48 | for t in range(1,y+1): 49 | steps=H-2+t-1 50 | result+=2**(factorial[steps]-factorial[steps-t+1]-factorial[t-1]-steps-1) 51 | 52 | #print result 53 | print("Case #"+str(caseNum)+": "+str(result)) 54 | caseNum+=1 55 | -------------------------------------------------------------------------------- /2020_RoundB/ref.py: -------------------------------------------------------------------------------- 1 | import fileinput 2 | from collections import Counter 3 | 4 | lines=[] 5 | for line in fileinput.input(): 6 | lines.append(line.rstrip()) 7 | 8 | seq=1 9 | caseNum=1 10 | 11 | while seq 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | int main(){ 9 | int trash; 10 | cin>>trash; 11 | for (int i=0;i>W>>H>>L>>U>>R>>D; 14 | unordered_map factorial; 15 | factorial[0]=0; 16 | double f=0; 17 | for(int j=1;j0 && y0){ 33 | for(int t=1;t0){ 43 | int steps=x-1+y-1; 44 | result+=pow(2,factorial[steps]-factorial[steps-x+1]-factorial[x-1]-steps); 45 | x++; 46 | y--; 47 | } 48 | if(x==H and y>0){ 49 | for(int t=1;t 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | int seen[20000001]; 12 | const int base=10000000; 13 | 14 | int main(){ 15 | int T; 16 | cin>>T; 17 | for(int tt=1;tt>N; 20 | long long result=0; 21 | memset(seen,0,sizeof seen); 22 | seen[base]=1; 23 | long long currentSum=base; 24 | for(int i=0;i>A; 27 | currentSum+=A; 28 | for(int s=0;;++s){ 29 | int st=s*s; 30 | if(currentSum-st<0){break;} 31 | result+=seen[currentSum-st]; 32 | } 33 | seen[currentSum]++; 34 | } 35 | 36 | 37 | cout<<"Case #"<=R or b<0 or b>=C or grid[a][b]!=grid[x][y]: 12 | continue 13 | if (a,b) in potential: 14 | continue 15 | potential.add((a,b)) 16 | if a!=R-1: 17 | p=grid[a+1][b] 18 | if p!=grid[x][y]: 19 | parent.add(p) 20 | children[p].add(grid[x][y]) 21 | q.append([a-1,b]) 22 | q.append([a,b+1]) 23 | q.append([a,b-1]) 24 | q.append([a+1,b]) 25 | 26 | for tt in range(1,T+1): 27 | R,C=raw_input().split() 28 | R,C=int(R),int(C) 29 | result="" 30 | grid=[] 31 | for i in range(R): 32 | row=raw_input() 33 | grid.append(row) 34 | seen=set() 35 | parent=defaultdict(set) 36 | children=defaultdict(set) 37 | for x in range(R): 38 | for y in range(C): 39 | if grid[x][y] not in seen: 40 | seen.add(grid[x][y]) 41 | dfs(grid,x,y,R,C,parent[grid[x][y]],children) 42 | 43 | s=deque() 44 | for k in parent: 45 | if len(parent[k])==0: 46 | s.append(k) 47 | 48 | while s: 49 | some=s.popleft() 50 | result+=some 51 | for n in children[some]: 52 | parent[n].discard(some) 53 | if len(parent[n])==0: 54 | s.append(n) 55 | del parent[n] 56 | parent.pop(some,None) 57 | 58 | if len(parent)>0: 59 | print "Case #"+str(tt)+": "+str(-1) 60 | else: 61 | print "Case #"+str(tt)+": "+str(result) 62 | 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /2020_RoundD/alienPiano.py: -------------------------------------------------------------------------------- 1 | 2 | T=int(raw_input()) 3 | 4 | for tt in range(1,T+1): 5 | K=int(raw_input()) 6 | A=[int(t) for t in raw_input().split()] 7 | result=10000 8 | dp=[[10001 for y in range(4)] for x in range(K)] 9 | dp[0][0]=0 10 | dp[0][1]=0 11 | dp[0][2]=0 12 | dp[0][3]=0 13 | for i in range(1,K): 14 | for j in range(4): 15 | for k in range(4): 16 | if A[i]>A[i-1]: 17 | if j>k: 18 | dp[i][j]=min(dp[i][j], dp[i-1][k]) 19 | elif j<=k: 20 | dp[i][j]=min(dp[i][j], dp[i-1][k]+1) 21 | elif A[i]=k: 25 | dp[i][j]=min(dp[i][j], dp[i-1][k]+1) 26 | else: 27 | if j==k: 28 | dp[i][j]=min(dp[i][j],dp[i-1][k]) 29 | else: 30 | dp[i][j]=min(dp[i][j],dp[i-1][k]+1) 31 | print "Case #"+str(tt)+": "+str(min(dp[K-1][0],dp[K-1][1],dp[K-1][2],dp[K-1][3])) 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /2020_RoundD/beautyTree.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | int N,A,B; 18 | vector> children; 19 | vector visited; 20 | vector timesA; 21 | vector timesB; 22 | 23 | void init(){ 24 | vector>v1(N+1); 25 | children=v1; 26 | vector v2; 27 | visited=v2; 28 | vector v3(N+1,0); 29 | timesA=v3; 30 | timesB=v3; 31 | } 32 | 33 | 34 | void dfs(int p){ 35 | visited.push_back(p); 36 | for(int x:children[p]){ 37 | dfs(x); 38 | } 39 | visited.pop_back(); 40 | 41 | timesA[p]++; 42 | timesB[p]++; 43 | int m=visited.size(); 44 | if(m-A>=0){ 45 | timesA[visited[m-A]]+=timesA[p]; 46 | } 47 | if(m-B>=0){ 48 | timesB[visited[m-B]]+=timesB[p]; 49 | } 50 | } 51 | 52 | int main(){ 53 | int T; 54 | cin>>T; 55 | 56 | for(int tt=1;tt>N>>A>>B; 58 | init(); 59 | 60 | int p; 61 | for(int i=2;i<=N;++i){ 62 | cin>>p; 63 | children[p].push_back(i); 64 | } 65 | 66 | dfs(1); 67 | //cout<<"timesA "<N: 14 | print "Case #"+str(tt)+": "+"IMPOSSIBLE" 15 | continue 16 | 17 | if N==2: 18 | if C==2: 19 | print "Case #"+str(tt)+": 2 2" 20 | continue 21 | 22 | if A==2 and B==1: 23 | print "Case #"+str(tt)+": 1 2" 24 | continue 25 | elif A==1 and B==2: 26 | print "Case #"+str(tt)+": 2 1" 27 | continue 28 | else: 29 | print "Case #"+str(tt)+": "+"IMPOSSIBLE" 30 | continue 31 | if A==C and B==C and C=2: 33 | r=" "+str(N)+" 1"*(N-C)+(" "+str(N))*(C-1) 34 | print "Case #"+str(tt)+":"+r 35 | continue 36 | print "Case #"+str(tt)+": "+"IMPOSSIBLE" 37 | continue 38 | 39 | if diff2>0: 40 | for x in range(N-C-diff1-diff2): 41 | result.append(1) 42 | for x in range(diff2): 43 | result.append(2) 44 | 45 | if diff2==0 and diff1>0: 46 | for x in range(N-C-diff1-diff2): 47 | result.appendleft(1) 48 | for x in range(diff1): 49 | result.appendleft(2) 50 | 51 | r="" 52 | for y in result: 53 | r+=" "+str(y) 54 | print "Case #"+str(tt)+":"+r 55 | 56 | -------------------------------------------------------------------------------- /2020_RoundE/longestArithmetic.py: -------------------------------------------------------------------------------- 1 | 2 | T=int(raw_input()) 3 | 4 | for tt in range(1,T+1): 5 | N=int(raw_input()) 6 | numbers=[int(t) for t in raw_input().split()] 7 | prev=-1 8 | current=0 9 | result=0 10 | for i in range(1,N): 11 | diff=numbers[i]-numbers[i-1] 12 | if diff==prev: 13 | current+=1 14 | else: 15 | prev=diff 16 | current=1 17 | result=max(result,current) 18 | print "Case #"+str(tt)+": "+str(result+1) -------------------------------------------------------------------------------- /2020_RoundE/toys.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | int N; 18 | int E[100001]; 19 | int R[100001]; 20 | 21 | struct cust{ 22 | bool operator()(const pair & a, const pair & b){ 23 | return a.first>T; 30 | 31 | 32 | 33 | for(int tt=1;tt>N; 35 | long long currentSum=0; 36 | for(int i=0;i>E[i]>>R[i]; 38 | currentSum+=E[i]; 39 | } 40 | priority_queue, vector>, cust> RE; 41 | 42 | long long maxTime=currentSum; 43 | long long currentTime=currentSum; 44 | int removed=0; 45 | 46 | for(int i=0;icurrentSum){ 50 | currentTime-=2*RE.top().second; 51 | currentSum-=RE.top().second; 52 | RE.pop(); 53 | } 54 | if(currentTime>maxTime){ 55 | maxTime=currentTime; 56 | removed=i+1-RE.size(); 57 | } 58 | else if(currentTime==maxTime){ 59 | removed=min(removed,(int)(i+1-RE.size())); 60 | } 61 | } 62 | if(!RE.empty()){ 63 | cout<<"Case #"< 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | //vector>graph(301); 18 | 19 | int main(){ 20 | int T; 21 | cin>>T; 22 | int N,X; 23 | int q; 24 | for(int tt=1;tt>N>>X; 26 | vector>numbers(N); 27 | for(int i=0;i>q;numbers[i]=make_pair((q-1)/X+1,i+1);} 28 | sort(numbers.begin(),numbers.end()); 29 | string result=""; 30 | for(int i=0;i=b: 16 | continue 17 | if coverage=0 and sx=0 and sy 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | 18 | vector>dp; 19 | long long N; 20 | 21 | int main(){ 22 | int T; 23 | cin>>T; 24 | double Ai; 25 | vectorempty; 26 | dp.push_back(empty); 27 | 28 | for(int i=1;i<=5000;++i){ 29 | vectorv1(i); 30 | dp.push_back(v1); 31 | } 32 | 33 | dp[1][0]=0; 34 | for(int i=2;i<=5000;++i){ 35 | // . . . . 36 | // .<-. . B . 37 | //the combine step happens before B, contribution from previous round 38 | for(int j=1;j<=i-1;++j){ 39 | dp[i][j] += dp[i-1][j-1]*(j)/(i-1); 40 | } 41 | 42 | // . . . . . 43 | // . . . B .<-. 44 | //the combine step happens after B, contribution from previous round 45 | for(int j=0;j<=i-2;++j){ 46 | dp[i][j] += dp[i-1][j]*(i-j-1)/(i-1); 47 | } 48 | 49 | //contribution in current round 50 | for(int j=1;j<=i-2;++j){ 51 | dp[i][j]+= ((double)2/(i-1)); 52 | } 53 | 54 | dp[i][0]+= (double)1/(i-1); 55 | dp[i][i-1]+= (double)1/(i-1); 56 | } 57 | 58 | for(int tt=1;tt>N; 61 | double result=0; 62 | for(int i=0;i>Ai; 64 | result+= dp[N][i]*Ai; 65 | } 66 | 67 | cout.precision(6); 68 | cout<<"Case #"<ref: 34 | break #greater than current val 35 | if j==l-1: 36 | r+=1 #acouunt for the last number 37 | else: 38 | if ref==0: 39 | break #nothing to do if smaller than 1 40 | index=bisect_left(A,ref) 41 | if j==l-1: 42 | r+=index 43 | else: 44 | r+=index*val[l-j-1] 45 | if index==5 or A[index]>ref: 46 | break #greater than current val 47 | if j==l-1: 48 | r+=1 #acouunt for the last number 49 | return r 50 | 51 | 52 | 53 | 54 | for tt in range(1,T+1): 55 | L,R=[int(t) for t in raw_input().split()] 56 | result= compute(R)-compute(L-1) 57 | 58 | print "Case #"+str(tt)+": "+str(result) 59 | 60 | 61 | -------------------------------------------------------------------------------- /2020_RoundH/retype.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | T=int(raw_input()) 3 | 4 | for tt in range(1,T+1): 5 | N,K,S=[int(t) for t in raw_input().split()] 6 | result=K-1 7 | result+=min(1+N, K-S+N-S+1) 8 | 9 | print "Case #"+str(tt)+": "+str(result) 10 | 11 | 12 | -------------------------------------------------------------------------------- /2020_RoundH/rugby.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | 18 | 19 | 20 | int main(){ 21 | int T; 22 | cin>>T; 23 | int N; 24 | long long Xi, Yi; 25 | 26 | for(int tt=1;tt>N; 29 | long long result=0; 30 | vectorY; 31 | vectorX; 32 | 33 | for(int i=0;i>Xi>>Yi; 35 | Y.push_back(Yi); 36 | X.push_back(Xi); 37 | } 38 | sort(Y.begin(),Y.end()); 39 | long long Ym= (Y[(N-1)/2]+Y[N/2])/2; 40 | 41 | sort(X.begin(),X.end()); 42 | vector computeX; 43 | for(int i=0;i 2 | LshapedPlots.py: dp in 4 directions.
3 | rabbitHouse.py: similar to trapping rain water(a leetcode problem), use heap.
4 | 5 | Checksum.py: The key is to convert the original problem into a graph problem: graph nodes are row numbers and column numbers, edges XY in the new graph are coordinates (x,y) in the original grid where grid\[x]\[y]=-1. Afterwards, we calulate the maximum spanning forest using prim's algorithm: 1. when there is no cluster, pick a random vertex and create a cluster to start with. 2. When there is a cluster under consideration, we keep track of the cut edges between current cluster and outside cluster, and always pick the max cut edge. If we keep track of the cut edges, the overall complexity is reduced to O(N^2).
6 | 7 | Note: all questions in this round can be safely passed using pypy2. In general pypy is slower than C++. 8 | -------------------------------------------------------------------------------- /2021_RoundA/checksum.py: -------------------------------------------------------------------------------- 1 | 2 | from collections import defaultdict 3 | T=int(raw_input()) 4 | 5 | for tt in range(1,T+1): 6 | N = int(raw_input()) 7 | points = [] 8 | for i in range(N): 9 | line =[int(t) for t in raw_input().split()] 10 | for j in range(N): 11 | if line[j]==-1: 12 | points.append([i,j]) 13 | 14 | graph = defaultdict(list) 15 | cost=[] 16 | for i in range(N): 17 | line =[int(t) for t in raw_input().split()] 18 | cost.append(line) 19 | R=raw_input() 20 | C=raw_input() 21 | 22 | total=0 23 | maxDist = defaultdict(lambda:-1) 24 | seen = [False for x in range(2*N)] 25 | vertices = set() 26 | for point in points: 27 | a,b= point 28 | w=cost[a][b] 29 | b+=N 30 | total+=w 31 | graph[a].append([b,w]) 32 | graph[b].append([a,w]) 33 | vertices.add(a) 34 | vertices.add(b) 35 | 36 | l=len(vertices) 37 | count=0 38 | maxForest=0 39 | while countg: 53 | maxV = p 54 | g = maxDist[p] 55 | seen[maxV]=True 56 | count+=1 57 | maxForest+=g 58 | for neighbor, w in graph[maxV]: 59 | if not seen[neighbor]: 60 | if w> maxDist[neighbor]: 61 | maxDist[neighbor]=w 62 | del maxDist[maxV] 63 | vertices.remove(maxV) 64 | 65 | 66 | print "Case #"+str(tt)+": "+str(total-maxForest) 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /2021_RoundA/rabbitHouse.py: -------------------------------------------------------------------------------- 1 | import heapq 2 | T=int(raw_input()) 3 | 4 | for tt in range(1,T+1): 5 | R,C = [int(t) for t in raw_input().split()] 6 | grid = [[0 for y in range(C)] for x in range(R)] 7 | result = 0 8 | q=[] 9 | seen = [[False for y in range(C)] for x in range(R)] 10 | minVal = [[0 for y in range(C)] for x in range(R)] 11 | for i in range(R): 12 | line = [int(t) for t in raw_input().split()] 13 | for j in range(len(line)): 14 | heapq.heappush(q, [-line[j], i, j]) 15 | minVal[i][j]=line[j] 16 | grid[i][j]=line[j] 17 | while q: 18 | val, i, j = heapq.heappop(q) 19 | val = -val 20 | if seen[i][j]: 21 | continue 22 | 23 | if val < minVal[i][j]: 24 | continue 25 | seen[i][j]=True 26 | result+= val-grid[i][j] 27 | if i and (val-1)>minVal[i-1][j]: 28 | minVal[i-1][j]=val-1 29 | heapq.heappush(q, [-val+1, i-1, j]) 30 | if iminVal[i+1][j]: 31 | minVal[i+1][j]=val-1 32 | heapq.heappush(q, [-val+1, i+1, j]) 33 | if j and (val-1)>minVal[i][j-1]: 34 | minVal[i][j-1]=val-1 35 | heapq.heappush(q, [-val+1, i, j-1]) 36 | if jminVal[i][j+1]: 37 | minVal[i][j+1]=val-1 38 | heapq.heappush(q, [-val+1, i, j+1]) 39 | 40 | 41 | print "Case #"+str(tt)+": "+str(result) 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /2021_RoundB/consecutivePrimes.py: -------------------------------------------------------------------------------- 1 | import math 2 | T=int(raw_input()) 3 | 4 | def testPrime(N): 5 | i=2 6 | while i*i<=N: 7 | if N%i==0: 8 | return False 9 | i+=1 10 | return True 11 | 12 | for tt in range(1,T+1): 13 | Z=int(raw_input()) 14 | mid = int(math.floor(math.sqrt(Z))) 15 | ref = mid 16 | firstSmall = -1 17 | secondSmall = -1 18 | while ref > 0: 19 | if testPrime(ref): 20 | if firstSmall<0: 21 | firstSmall = ref 22 | else: 23 | secondSmall = ref 24 | break 25 | ref -= 1 26 | ref = mid+1 27 | firstBig = -1 28 | #print str(firstSmall)+" "+str(secondSmall) 29 | while refword[i-1]: 11 | local+=1 12 | else: 13 | local = 1 14 | result[i] = str(local) 15 | 16 | print "Case #"+str(tt)+": "+" ".join(result) 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /2021_RoundB/longestRegression.py: -------------------------------------------------------------------------------- 1 | 2 | T=int(raw_input()) 3 | 4 | def compute(numbers): 5 | result = 2 6 | i=0 7 | 8 | while i
2 | cuttingIntervals.py: flatten the intervals into time events, get (intervals with max cuts information) in between start events and end events. And then sort the (intervals with max cuts information) based on max cut that can be achieved.

3 | finalExam.cpp: we utilize the c++ map data structure to help us achieve log N complexity insert and log N complexity delete. We store the difficulty intervals in a map structure, and modify it as we choose and assign to students, using binary search.

4 | PrimesAndQueris.cpp: first pre - req is that we understand lifting-the-exponent lemma. Then since N is within the range of 5 * 10^5, and also based on the hint that we have range sum queries and point update, we would want to look at structures such as segment tree. After the data structure is chosen, we examine the formulas outlined in lifting-the-exponent lemma, and break it into several segment trees.

5 | -------------------------------------------------------------------------------- /2021_RoundD/arithmeticSquare.py: -------------------------------------------------------------------------------- 1 | T = int(raw_input()) 2 | from collections import Counter 3 | for tt in range(1,T+1): 4 | l1 = [int(t) for t in raw_input().split()] 5 | l2 = [int(t) for t in raw_input().split()] 6 | l3 = [int(t) for t in raw_input().split()] 7 | c = Counter() 8 | 9 | numbers = [(l1[0]+l3[2]), (l1[2]+l3[0]), (l2[0]+l2[1]), l1[1]+l3[1]] 10 | for num in numbers: 11 | if num%2==0: 12 | c[num/2]+=1 13 | r = 0 14 | for key in c: 15 | if c[key]>r: 16 | r=c[key] 17 | 18 | base = 0 19 | if l1[1]*2 == l1[0]+l1[2]: 20 | base+=1 21 | if l3[1]*2 == l3[0]+l3[2]: 22 | base+=1 23 | if l2[0]*2 == l1[0]+l3[0]: 24 | base+=1 25 | if l2[1]*2 == l1[2]+l3[2]: 26 | base+=1 27 | 28 | print "Case #"+str(tt)+": "+str(base+r) 29 | -------------------------------------------------------------------------------- /2021_RoundD/cuttingIntervals.py: -------------------------------------------------------------------------------- 1 | T = int(raw_input()) 2 | from collections import Counter 3 | import heapq 4 | for tt in range(1,T+1): 5 | N,C = [int(t) for t in raw_input().split()] 6 | 7 | x = Counter() 8 | for i in range(N): 9 | a,b = [int(t) for t in raw_input().split()] 10 | x[a+1] += 1 11 | x[b] -=1 12 | 13 | #print x 14 | l2 = [] 15 | for start in x: 16 | quantity = x[start] 17 | l2.append([start, quantity]) 18 | l2.sort() 19 | #print l2 20 | base = 0 21 | for i in range(len(l2)): 22 | base += l2[i][1] 23 | l2[i][1] = base 24 | #print l2 25 | 26 | l3 = [] 27 | for i in range(1, len(l2)): 28 | interval = l2[i][0]-l2[i-1][0] 29 | value = l2[i-1][1] 30 | if interval > 0 and value>0: 31 | l3.append([-value, interval]) 32 | 33 | l3.sort() 34 | #print l3 35 | 36 | r = 0 37 | idx = 0 38 | while idx0: 39 | cut, many = l3[idx] 40 | cut = -cut 41 | if many<=C: 42 | C-=many 43 | r += many*cut 44 | else: 45 | r += C*cut 46 | break 47 | idx+=1 48 | 49 | 50 | print "Case #"+str(tt)+": "+str(r+N) 51 | -------------------------------------------------------------------------------- /2021_RoundE/README.md: -------------------------------------------------------------------------------- 1 | shuffledAnagrams.py: key observation is that any character cannot be more than half. we sort the sequence and chop them into halves, and swap the two halves. Another variation of this solution can be applied to generate random matchings for groups as well.

2 | birthdayCake.py: the official solution provided detailed analysis on lower bound and upper bound. In the end, we cut out borders first, and then deal with the inner topology based on K\*K blocks.

3 | palindromicCrossword.py: standard dfs. Remember to avoid max recursion depth if you are using python.

4 | IncreasingSequenceCardGame.py: the key observation is the dp relation such that, depending on the top card X, the sub pile could be reduced to a pile of cards greater than the top card X, and therefore reduced to a previous problem. i.e. a pile of cards from X+1 to N, produces the same result as a pile of cards from 1 to N-X. approximations can be applied on top of dp relations.

5 | -------------------------------------------------------------------------------- /2021_RoundE/birthdayCake.py: -------------------------------------------------------------------------------- 1 | 2 | import math 3 | T=int(raw_input()) 4 | 5 | 6 | for tt in range(1,T+1): 7 | R, C, K = [int(x) for x in raw_input().split()] 8 | r1, c1, r2, c2 = [int(x) for x in raw_input().split()] 9 | m = r2 - r1 + 1 10 | n = c2 - c1 + 1 11 | base = 0 12 | 13 | minR = min(r1-1, R- r2) 14 | minC = min(c1-1, C- c2) 15 | minBoundR = (minR + m - 1) /K +1 + ( m - 1 ) /K +1 + 2 * ((n - 1)/K + 1) 16 | minBoundC = (minC + n - 1) /K +1 + ( n - 1) /K +1 + 2 * ((m -1)/K + 1) 17 | base = min(minBoundC, minBoundR) 18 | 19 | if r1 == 1 or r2 == R or c1 == 1 or c2 == C: 20 | base = 0 21 | if r1 != 1: 22 | base += (n-1)/K + 1 23 | if r2 != R: 24 | base += (n-1)/K + 1 25 | if c1 != 1: 26 | base += (m-1)/K + 1 27 | if c2 != C: 28 | base += (m-1)/K + 1 29 | 30 | if K>= n or K>= m: 31 | base += n*m - 1 32 | else: 33 | base += m*n - 1 + ((n-1)/K) * ((m-1)/K) 34 | print "Case #"+str(tt)+": "+str(base) 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /2021_RoundE/increasingCardGame.py: -------------------------------------------------------------------------------- 1 | 2 | import math 3 | T=int(raw_input()) 4 | 5 | bound = int(1e6) 6 | 7 | prefixSum = 0 8 | res = [0 for x in range(bound+1)] 9 | for i in range(1, bound+1): 10 | prefixSum += res[i-1] 11 | res[i] = prefixSum * 1.0 / i + 1 12 | 13 | logConstant = res[bound] - math.log(bound + 1) 14 | 15 | for tt in range(1,T+1): 16 | N = int(raw_input()) 17 | if N <= bound: 18 | print "Case #"+str(tt)+": "+str(res[N]) 19 | else: 20 | approximate = math.log(N+1) + logConstant 21 | print "Case #"+str(tt)+": "+str(approximate) 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /2021_RoundE/shuffledAnagrams.py: -------------------------------------------------------------------------------- 1 | 2 | from collections import defaultdict, Counter 3 | T=int(raw_input()) 4 | 5 | for tt in range(1,T+1): 6 | S= raw_input() 7 | 8 | chars = [] 9 | l = len(S) 10 | countMap = Counter(S) 11 | imposs = False 12 | for i in range(l): 13 | if countMap[S[i]] > l/2: 14 | imposs = True 15 | break 16 | if imposs: 17 | print "Case #"+str(tt)+": "+"IMPOSSIBLE" 18 | continue 19 | for i in range(l): 20 | chars.append([S[i], i]) 21 | chars.sort() 22 | 23 | res = [None for x in range(l)] 24 | for i in range(l): 25 | if i < l/2: 26 | res[chars[i][1]] = chars[i + l/2][0] 27 | else: 28 | res[chars[i][1]] = chars[i - (l+1)/2][0] 29 | 30 | print "Case #"+str(tt)+": "+"".join(res) 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /2021_RoundF/README.md: -------------------------------------------------------------------------------- 1 | trashBin.py: easy to solve, one can follow official analysis.

2 | Festival : Here, I would like to present a way of solving the question without having to use a segment tree, and also produces an equally good run time complexity as compared to that suggested by the official solution. First of all, we still transform all festival into start and end events, and sort them based on timestamps. Now, as we iterate over all these events, we maintain two heaps, one min heap, and the other one is a max heap. At a certain timestamp t, if we encounter a start event, we try to add the festival into the min heap. If the capacity is more than K, we pop the minimum value from the min heap and put it into the max heap. If later a lot of festivals end, and the min heap is smaller than size K, we could pop from the max heap and add festivals back into the min heap. We also keep a set to track all the invalid festival ids. As we iterate, we keep track of the maximum sum of happiness of festivals in the min heap, which would be our final answer. The overall complexity is N log N (sort) + N log N (heap push and pop), which is N log N. Details can be found in my implementation.

3 | StarTrappers.py: We consider the triangles and the four_sided_polygons. For the four_sided_polygons, we only consider those at the intersection of the diagonals. To group the diagnols, I choose the numerator / denominator integer pairs as the hash keys. After divided by a greatest common divisor, numerator / denominator pairs can represent the tangent angles uniquely, and without loss of any precision.

4 | graphTravel.cpp: we use 16 bits to record all possible room combinations, and can compute the magic scores for each combination. As we iterate from state 0 to state (1<<15), at each state X, we find all of the next reachable states. For each reachable state Y, we add ways\[X] to ways\[Y], where ways\[] represents the number of unique ways to reach that state. And along the way, we add up all ways\[X] where score\[X] is K. This sum is our final result. 5 | -------------------------------------------------------------------------------- /2021_RoundF/trashBins.py: -------------------------------------------------------------------------------- 1 | import sys 2 | T=int(raw_input()) 3 | 4 | for tt in range(1,T+1): 5 | N=int(raw_input()) 6 | bins = raw_input() 7 | dp = [0 for x in range(N)] 8 | prev = -1 9 | for i in range(N): 10 | if bins[i] == "1": 11 | prev = i 12 | continue 13 | else: 14 | if prev < 0: 15 | dp[i] = sys.maxint 16 | else: 17 | dp[i] = i - prev 18 | #print dp 19 | 20 | prev = -1 21 | result = 0 22 | for j in range(N-1,-1,-1): 23 | if bins[j] == "1": 24 | prev = j 25 | continue 26 | else: 27 | if prev < 0: 28 | result += dp[j] 29 | continue 30 | else: 31 | #print "at pos "+str(j)+" "+str(min(dp[j], prev-j)) 32 | result += min(dp[j], prev-j) 33 | 34 | 35 | 36 | 37 | print "Case #"+str(tt)+": "+str(result) 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /2021_RoundG/Banana.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | import sys 3 | T=int(raw_input()) 4 | 5 | for tt in range(1,T+1): 6 | N, K = [int(x) for x in raw_input().split()] 7 | B = [int(y) for y in raw_input().split()] 8 | minLengthForSum = [sys.maxint for y in range(K+1)] 9 | minLengthForSum[0] = 0 10 | ans = sys.maxint 11 | for i in range(N): 12 | secondSum = 0 13 | for j in range(i, N): 14 | secondSum += B[j] 15 | if secondSum > K: 16 | break 17 | if minLengthForSum[K - secondSum]!= -1: 18 | ans = min(ans, minLengthForSum[K-secondSum] + j-i+1) 19 | 20 | firstSum = 0 21 | for j in range(i,-1,-1): 22 | firstSum += B[j] 23 | if firstSum > K: 24 | break 25 | if minLengthForSum[firstSum] == -1: 26 | minLengthForSum[firstSum] = i-j+1 27 | else: 28 | minLengthForSum[firstSum] = min(minLengthForSum[firstSum], i-j+1) 29 | if ans == sys.maxint: 30 | ans = -1 31 | 32 | print "Case #"+str(tt)+": "+str(ans) 33 | -------------------------------------------------------------------------------- /2021_RoundG/README.md: -------------------------------------------------------------------------------- 1 | DogsAndCats: simulation of the process.
2 |
3 | StayingHyradted: First of all similar to previous google problems, we break the problem into two separate problems, one along the x - axis, and the other along the y - axis. Along each axis, we try to find the balancing point, and that point should always happen on a start event or an end event of a rectangle. (for example, a rectangle ranging from 2 to 4 along one side has a start event at 2, and an end event at 4). We can either find this point by binary search or simple iteration, since the overall time complexity is bounded by sorting, which costs N log N.
4 |
5 | BananaBunches: Suppose we have two segments L1 and L2, Where L1 + L2 has a total length of N. As we iterate from left to right, and as the size of L1 is growing, we want to know: in L2, what is the minimum length to create a sum S. But if we move from left to right, then L2 is becoming smaller and smaller, and we do not have a convenient way to maintain all the optimal sums. On the other hand, if we move from right to left, we can keep track of all the optimal sums that are in L2, and add more sums to it as we iterate. In summary, we move from right to left, building possible sums in L1 starting from current index, and also use information of the optimal sums that has been building up in L2.
6 |
7 | simplePolygon: Pick's theorem was my favorite grid formula back in high school. I haven't used it for decade since high school and am thrilled to see it again today. 8 |
9 | -------------------------------------------------------------------------------- /2021_RoundG/dogsAndCats.py: -------------------------------------------------------------------------------- 1 | import sys, heapq 2 | from collections import defaultdict 3 | T=int(raw_input()) 4 | 5 | for tt in range(1,T+1): 6 | N,D,C,M = [int(x) for x in raw_input().split()] 7 | S = raw_input() 8 | i = 0 9 | while i ord('z'): 19 | temp = ord('a') 20 | 21 | temp = ord(char) 22 | countBackward = 0 23 | while temp not in validSet: 24 | temp -= 1 25 | countBackward += 1 26 | if temp < ord('a'): 27 | temp = ord('z') 28 | 29 | result += min(countForward, countBackward) 30 | 31 | print "Case #"+str(tt)+": "+str(result) 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /2022_RoundA/challengeNine.py: -------------------------------------------------------------------------------- 1 | 2 | from collections import defaultdict 3 | import heapq 4 | T=int(input()) 5 | 6 | for tt in range(1,T+1): 7 | numberString = input() 8 | number = [int(x) for x in numberString] 9 | tsum = sum(number) 10 | adder = 9 - (tsum % 9) 11 | if adder == 9: 12 | adder = 0 13 | 14 | if adder == 0: 15 | l = len(number) 16 | res = '' 17 | for i in range(1,l): 18 | if adder < number[i]: 19 | res = numberString[:i] + str(adder) + numberString[i:] 20 | break 21 | if res == '': 22 | res = numberString + str(adder) 23 | res = "Case #"+str(tt)+": "+res 24 | print(res) 25 | continue 26 | 27 | l = len(number) 28 | res = '' 29 | for i in range(l): 30 | if adder < number[i]: 31 | res = numberString[:i] + str(adder) + numberString[i:] 32 | break 33 | #print('i is '+str(i)) 34 | if res == '': 35 | res = numberString + str(adder) 36 | res = "Case #"+str(tt)+": "+res 37 | 38 | print(res) 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /2022_RoundA/palindromeFree.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | 3 | T=int(input()) 4 | 5 | def palindrome5(r, left, right): 6 | while left < right: 7 | if ((r & (1<>left) != ((r & (1<>right): 8 | return False 9 | left += 1 10 | right -= 1 11 | return True 12 | 13 | def dfs(s, start, r, state): 14 | if start == 5: 15 | if not palindrome5(r, 0, 4): 16 | state[r] = True 17 | return 18 | 19 | if s[start] == '0': 20 | dfs(s, start+1, r, state) 21 | elif s[start] == '1': 22 | dfs(s, start+1, r | (1<> 1)] = True 36 | if state[i] and (s[start] == '?' or s[start] == '0'): 37 | sixDigit = i 38 | if (not palindrome5(sixDigit, 1, 5)) and (not palindrome5(sixDigit, 0, 5)): 39 | newState[(sixDigit >> 1)] = True 40 | state = newState 41 | 42 | # start == len(s): 43 | for i in range(1<<5): 44 | if state[i]: 45 | return 'POSSIBLE' 46 | return 'IMPOSSIBLE' 47 | 48 | 49 | for tt in range(1,T+1): 50 | ans = '*' 51 | l = int(input()) 52 | s = input() 53 | if l < 5: 54 | print("Case #"+str(tt)+": "+'POSSIBLE') 55 | continue 56 | state = [False for x in range(1<<5)] 57 | dfs(s, 0, 0, state) 58 | res = findPossible(s, 5, state) 59 | 60 | print("Case #"+str(tt)+": "+res) 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /2022_RoundA/speedTyping.py: -------------------------------------------------------------------------------- 1 | 2 | from collections import defaultdict 3 | import heapq 4 | T=int(input()) 5 | 6 | for tt in range(1,T+1): 7 | I = input() 8 | P = input() 9 | p1=0 10 | p2=0 11 | r = "IMPOSSIBLE" 12 | count = 0 13 | while p1 < len(I) and p2< len(P): 14 | #print 'p2 is '+str(p2)+" p1 is "+str(p1) 15 | 16 | if P[p2] != I[p1]: 17 | count+=1 18 | p2+=1 19 | else: 20 | p1+=1 21 | p2+=1 22 | if p1 == len(I) and p2 == len(P): 23 | r = count 24 | if p2== len(P) and p1 2 | 3 | 1.infinityArea : nit. can be solved following official solution.
4 | 2.palindromicFactors : nit. can be solved following official solution.

5 | 3. unlockThePadlock: According to the spec, all rotations are strictly inclusive. (there can't be partially overlap rotation ranges). 6 | Suppose we do rotations from larger ranges to smaller ranges. Now, consider an outer rotation of the range \[A .... B\], there could only be 3 situations for the next inner rotation.
7 |     i. the inner rotation is \[M .... N\], where M > A and N < B. In this case, the amount rotated is the same from both ends (considering either from A's end or from B's end)
8 |     ii. the inner rotation is \[A .... N\], where N < B. In this case, the amount rotated in this cycle must be calculated from B's side.
9 |     iii. the inner rotation is \[M .... B\], where M > A. In this case, the amount rotated in this cycle must be calculated from A's side.
10 | therefore, the dp transition from the outer range to the inner range can be achieved, either through rotation on A's end, or through rotation on B's end. With this understanding, the rest can be understood by reading the official analysis.

11 | 4. Hamiltonian Tour: the key is how to combine established cycles. Suppose we have two cycles 'SENW' and 'SENW' next to each other, if we know the relative orientation of the two smaller cycles, we can combine the two cycles by changing the neighboring flow. e.g. if the second cycle is on the right of the first cycle, we can make the two cycles 'SEEW' and 'WENW' by changing first cycle's thrid edge flow, and the second cycle's first edge flow. To obtain the relative orientation of neighboring cycles, we use an iterative dfs traversal to record the relative positions.
12 | -------------------------------------------------------------------------------- /2022_RoundB/infinityArea.py: -------------------------------------------------------------------------------- 1 | from random import randint 2 | import math 3 | T=int(input()) 4 | 5 | 6 | for tt in range(1,T+1): 7 | R, A, B = [int(x) for x in input().split()] 8 | area = 0 9 | r = R 10 | res = 0 11 | count = 0 12 | while r>0: 13 | res += math.pi * r**2 14 | if count % 2==0: 15 | r *= A 16 | else: 17 | r = int(r/B) 18 | count+=1 19 | 20 | print('Case #'+str(tt)+": "+str(res)) 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /2022_RoundB/palindromicFactors.py: -------------------------------------------------------------------------------- 1 | 2 | T=int(input()) 3 | 4 | def isPal(A): 5 | A = str(A) 6 | l = 0 7 | r = len(A)-1 8 | while l end: 8 | return 0 9 | if dp[start][end][fromLeft] != inf: 10 | return dp[start][end][fromLeft] 11 | 12 | count = 0 13 | if fromLeft == 0: 14 | if start != 0: 15 | count = numbers[start-1] 16 | 17 | else: 18 | if end != len(numbers)-1: 19 | count = numbers[end+1] 20 | 21 | startVal = (numbers[start] - count + D)%D 22 | endVal = (numbers[end] - count + D) %D 23 | operations = min(startVal, D-startVal) 24 | val1 = operations + compute(start+1, end, 0, numbers, D) 25 | operations = min(endVal, D-endVal) 26 | val2 = operations + compute(start, end-1, 1, numbers, D) 27 | val = min(val1, val2) 28 | dp[start][end][fromLeft] = val 29 | return val 30 | 31 | for tt in range(1,T+1): 32 | N, D = [int(x) for x in input().split()] 33 | numbers = [int(x) for x in input().split()] 34 | dp = [[[inf for z in range(2)] for y in range(401)] for x in range(401)] 35 | res = compute(0,N-1,0,numbers, D) 36 | 37 | print('Case #'+str(tt)+": "+str(res)) 38 | 39 | 40 | -------------------------------------------------------------------------------- /2022_RoundC/antsOnAStick.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | T=int(input()) 3 | 4 | for tt in range(1,T+1): 5 | N, L = [int(x) for x in input().split()] 6 | dir = [None for x in range(N)] 7 | event = [] 8 | ant_array = [] 9 | for i in range(N): 10 | position, direction = [int(x) for x in input().split()] 11 | if direction == 0: 12 | event.append([position, 0]) 13 | else: 14 | event.append([L - position, 1]) 15 | ant_array.append([position, i+1]) 16 | event.sort() 17 | ant_array.sort() 18 | 19 | p1 = 0 20 | p2 = N-1 21 | res = '' 22 | 23 | fall_array = [] 24 | for e in event: 25 | time, side = e 26 | if side == 0: 27 | fall_array.append([time, ant_array[p1][1]]) 28 | p1 += 1 29 | else: 30 | fall_array.append([time, ant_array[p2][1]]) 31 | p2 -= 1 32 | fall_array.sort() 33 | res = "Case #"+str(tt)+": "+" ".join([str(x[1]) for x in fall_array]) 34 | print(res) 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /2022_RoundC/newPassword.py: -------------------------------------------------------------------------------- 1 | from curses.ascii import isalnum 2 | 3 | 4 | T=int(input()) 5 | 6 | for tt in range(1,T+1): 7 | N = int(input()) 8 | password = input() 9 | hasUpper = False 10 | hasLower = False 11 | hasDigit = False 12 | hasSpecial = False 13 | for char in password: 14 | if char.isalpha() and char.islower(): 15 | hasLower = True 16 | if char.isalpha() and char.isupper(): 17 | hasUpper = True 18 | if char.isdigit(): 19 | hasDigit = True 20 | if char in '#@*&': 21 | hasSpecial = True 22 | if not hasUpper: 23 | password += 'A' 24 | if not hasLower: 25 | password += 'a' 26 | if not hasDigit: 27 | password += '0' 28 | if not hasSpecial: 29 | password += '@' 30 | if len(password) < 7: 31 | password += 'a' * ( 7- len(password)) 32 | print("Case #"+str(tt)+": "+password) 33 | 34 | 35 | -------------------------------------------------------------------------------- /2022_RoundC/palindromicDeletions.py: -------------------------------------------------------------------------------- 1 | T=int(input()) 2 | 3 | mod = int(1e9+7) 4 | dp = [[[0 for z in range(402)] for y in range(402)] for x in range(402)] 5 | 6 | def power(x,y): 7 | if y == 0: 8 | return 1 9 | child_power = power(x, y >> 1) 10 | my_power = child_power * child_power % mod 11 | if (y & 1): 12 | my_power = my_power * x % mod 13 | return my_power % mod 14 | 15 | def get_inv(x): 16 | return power(x, mod - 2) 17 | 18 | fac = [1 for x in range(401)] 19 | rev_fac = [400 for x in range(402)] 20 | rev_fac[401] = 1 21 | for i in range(1, 401): 22 | fac[i] = i * fac[i-1] % mod 23 | 24 | for tt in range(1,T+1): 25 | N = int(input()) 26 | S = input() 27 | 28 | 29 | for str_len in range(1, N+1): 30 | for start in range(0, N - str_len + 1): 31 | end = start + str_len - 1 32 | dp[start][end][0] = 1 33 | dp[start][end][1] = end - start + 1 34 | for len in range(2, str_len+1): # this len is length of palindrome 35 | dp[start][end][len] = 0 36 | dp[start][end][len] = (dp[start][end][len] + dp[start+1][end][len]) % mod 37 | dp[start][end][len] = (dp[start][end][len] + dp[start][end-1][len]) % mod 38 | dp[start][end][len] = (dp[start][end][len] - dp[start+1][end-1][len] + mod) % mod 39 | if S[start] == S[end]: 40 | if start == end - 1: 41 | dp[start][end][len] = (dp[start][end][len] + 1) % mod 42 | else: 43 | dp[start][end][len] = (dp[start][end][len] + dp[start+1][end-1][len-2]) % mod 44 | 45 | result = 0 46 | for count in range(0, N): # the original string does not count according to the rules 47 | result = result + dp[0][N-1][count] % mod * fac[count] % mod * fac[N-count] % mod 48 | # lets just use fermat's little theorem instead of something fancy 49 | result = result * power(fac[N], mod - 2) % mod 50 | 51 | print("Case #"+str(tt)+": "+str(result)) 52 | -------------------------------------------------------------------------------- /2022_RoundC/rangePartition.py: -------------------------------------------------------------------------------- 1 | T=int(input()) 2 | 3 | for tt in range(1,T+1): 4 | N , X, Y= [int(x) for x in input().split()] 5 | my_sum = sum([x for x in range(1,N+1)]) 6 | if (X+Y) > my_sum or my_sum % (X+Y) != 0: 7 | print("Case #"+str(tt)+": "+"IMPOSSIBLE") 8 | else: 9 | print("Case #"+str(tt)+": "+"POSSIBLE") 10 | my_sum = int(my_sum / (X+Y) * X) 11 | current_big = N 12 | res = [] 13 | while my_sum > 0: 14 | if my_sum > current_big: 15 | res.append(current_big) 16 | my_sum -= current_big 17 | current_big -= 1 18 | elif my_sum <= current_big: 19 | res.append(my_sum) 20 | break 21 | print(len(res)) 22 | print(" ".join([str(x) for x in res])) 23 | 24 | 25 | -------------------------------------------------------------------------------- /2022_RoundD/imageLabeler.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict, deque 2 | T=int(input()) 3 | 4 | for tt in range(1,T+1): 5 | N, M = [int(x) for x in input().split()] 6 | numbers = [int(x) for x in input().split()] 7 | numbers.sort(key = lambda x: -x) 8 | last_size = N-M+1 9 | if last_size % 2 ==0: 10 | start = numbers[M - 1 + int(max(last_size - 1, 0) / 2)] 11 | end = numbers[M - 1 + int(last_size / 2)] 12 | pivot = (start + end) / 2.0 13 | else: 14 | pivot = numbers[M - 1 + int(last_size/2)] 15 | numbers[M-1] = pivot 16 | res = sum(numbers[:M]) 17 | print("Case #"+str(tt)+": "+str(res)) 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /2022_RoundD/maximumGain.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict, deque 2 | T=int(input()) 3 | 4 | for tt in range(1,T+1): 5 | N = int(input()) 6 | a_array = [int(x) for x in input().split()] 7 | M = int(input()) 8 | b_array = [int(x) for x in input().split()] 9 | K = int(input()) 10 | 11 | prefix_a = [0] 12 | for a in a_array: 13 | prefix_a.append(prefix_a[-1] + a) 14 | postfix_a = [0] 15 | for i in range(N-1, -1, -1): 16 | postfix_a.append(postfix_a[-1] + a_array[i]) 17 | 18 | prefix_b = [0] 19 | for b in b_array: 20 | prefix_b.append(prefix_b[-1] + b) 21 | postfix_b = [0] 22 | for i in range(M-1, -1, -1): 23 | postfix_b.append(postfix_b[-1] + b_array[i]) 24 | 25 | result = 0 26 | for s1 in range( max(0, K-M), min(K+1, N+1)): 27 | s2 = K - s1 28 | sum_1 = 0 29 | for front in range(s1+1): 30 | sum_1 = max(sum_1, prefix_a[front] + postfix_a[s1 - front]) 31 | sum_2 = 0 32 | for front in range(s2+1): 33 | sum_2 = max(sum_2, prefix_b[front] + postfix_b[s2 - front]) 34 | result = max(result, sum_1 + sum_2) 35 | 36 | res = "Case #"+str(tt)+": "+str(result) 37 | print(res) 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /2022_RoundE/MatchingPalindrome.py: -------------------------------------------------------------------------------- 1 | 2 | T=int(input()) 3 | 4 | def checkPalindrome(S, i): 5 | left = i 6 | right = len(S)-1 7 | while left < right: 8 | if S[left] == S[right]: 9 | left += 1 10 | right -= 1 11 | else: 12 | return False 13 | return True 14 | 15 | for tt in range(1,T+1): 16 | N = int(input()) 17 | S = input() 18 | result = N 19 | for i in range(1,N+1): 20 | if N%i==0 and checkPalindrome(S, i): 21 | result = i 22 | break 23 | 24 | print("Case #"+str(tt)+": "+str(S[:i][::-1])) 25 | 26 | 27 | -------------------------------------------------------------------------------- /2022_RoundE/coloringGame.py: -------------------------------------------------------------------------------- 1 | from bisect import bisect 2 | T=int(input()) 3 | import math 4 | 5 | for tt in range(1,T+1): 6 | N = int(input()) 7 | 8 | print("Case #"+str(tt)+": "+str(max(1, math.ceil(N/5)))) 9 | 10 | 11 | -------------------------------------------------------------------------------- /2022_RoundE/studentsAndMentors.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | using namespace std; 17 | 18 | typedef long long ll; 19 | 20 | int main() 21 | { 22 | int t; 23 | cin>>t; 24 | for(int ca=1;ca<=t;ca++) 25 | { 26 | int N; 27 | cin>>N; 28 | vector students(N); 29 | for(int i=0;i>students[i]; 31 | } 32 | string result = ""; 33 | vector sorted_students = students; 34 | sort(sorted_students.begin(), sorted_students.begin()+N); 35 | for(int s:students){ 36 | int pos = upper_bound(sorted_students.begin(), sorted_students.begin()+N, 2*s) - sorted_students.begin(); 37 | if(pos == 0){ 38 | result += " -1"; 39 | }else{ 40 | if(sorted_students[pos - 1] == s){ 41 | if(pos == 1){ 42 | result += " -1"; 43 | }else{ 44 | result += " "+to_string(sorted_students[pos-2]); 45 | } 46 | }else{ 47 | result += " "+to_string(sorted_students[pos-1]); 48 | } 49 | } 50 | } 51 | 52 | 53 | printf("Case #%d: %s\n",ca, result.c_str()); 54 | } 55 | return 0; 56 | } -------------------------------------------------------------------------------- /2022_RoundF/sortTheFabrics.py: -------------------------------------------------------------------------------- 1 | 2 | T=int(input()) 3 | import math 4 | 5 | for tt in range(1,T+1): 6 | N = int(input()) 7 | fabrics = [] 8 | for i in range(N): 9 | color, durability, id = input().split() 10 | durability, id = int(durability), int(id) 11 | fabrics.append([color, durability, id]) 12 | arr_1 = sorted(fabrics, key = lambda x:(x[0], x[2])) 13 | arr_2 = sorted(fabrics, key = lambda x:(x[1], x[2])) 14 | result = 0 15 | for i in range(N): 16 | if arr_1[i] == arr_2[i]: 17 | result += 1 18 | 19 | print("Case #"+str(tt)+": "+str(result)) 20 | 21 | 22 | -------------------------------------------------------------------------------- /2022_RoundF/storyOfSeasons.py: -------------------------------------------------------------------------------- 1 | 2 | T=int(input()) 3 | from collections import defaultdict, deque 4 | import heapq 5 | 6 | for tt in range(1,T+1): 7 | D, N, X = [int(x) for x in input().split()] 8 | seeds = [] 9 | pending_list = [] 10 | days_deadline = [] 11 | for i in range(N): 12 | quantity, growth_days, profit = [int(x) for x in input().split()] 13 | pending_list.append([growth_days, -profit, quantity]) 14 | # beaware of days == D 15 | if growth_days < D: 16 | days_deadline.append(growth_days) 17 | pending_list.sort(key = lambda x: -x[0]) 18 | days_deadline.append(D) 19 | days_deadline.sort() 20 | 21 | result = 0 22 | previous_day = 0 23 | for current_day in days_deadline: 24 | # calculate profit for the intervals of days between [1 day before the current day, to previous_day] 25 | # i.e. current_day - 1 - previous_day + 1 == current_day - previous_day 26 | head_count = X * (current_day - previous_day) 27 | # add all crops that could only start from the previous_day (the previous cutoff) 28 | while pending_list and current_day > pending_list[-1][0]: 29 | growth_days, neg_profit, quantity = pending_list.pop() 30 | heapq.heappush(seeds, (neg_profit, quantity)) 31 | while seeds and head_count > 0: 32 | neg_profit, quantity = seeds[0] 33 | profit = - neg_profit 34 | if head_count >= quantity: 35 | result += quantity * profit 36 | heapq.heappop(seeds) 37 | head_count -= quantity 38 | elif head_count < quantity: 39 | result += head_count * profit 40 | heapq.heappop(seeds) 41 | heapq.heappush(seeds, (neg_profit, quantity - head_count)) 42 | head_count = 0 43 | previous_day = current_day 44 | 45 | print("Case #"+str(tt)+": "+str(result)) 46 | 47 | 48 | -------------------------------------------------------------------------------- /2022_RoundF/waterContainerSystem.py: -------------------------------------------------------------------------------- 1 | 2 | T=int(input()) 3 | from collections import defaultdict, deque 4 | from bisect import bisect, bisect_left, bisect_right 5 | 6 | for tt in range(1,T+1): 7 | N, Q = [int(x) for x in input().split()] 8 | graph = defaultdict(lambda: []) 9 | for i in range(N-1): 10 | a, b = [int(x) for x in input().split()] 11 | graph[a].append(b) 12 | graph[b].append(a) 13 | q = deque([[1, 0]]) 14 | geo = [] 15 | seen = set() 16 | while q: 17 | current_node, depth = q.popleft() 18 | if current_node in seen: 19 | continue 20 | seen.add(current_node) 21 | if depth == len(geo): 22 | geo.append(0) 23 | geo[depth] += 1 24 | if current_node in graph: 25 | for kid in graph[current_node]: 26 | if kid not in seen: 27 | q.append([kid, depth+1]) 28 | 29 | for i in range(1,len(geo)): 30 | geo[i] += geo[i-1] 31 | 32 | for j in range(Q): 33 | _ = input() 34 | 35 | pos = bisect_left(geo, Q) 36 | result = -1 37 | if geo[pos] == Q: 38 | result = geo[pos] 39 | else: 40 | result = geo[pos - 1] 41 | 42 | print("Case #"+str(tt)+": "+str(result)) 43 | 44 | 45 | -------------------------------------------------------------------------------- /2022_RoundG/Curling.py: -------------------------------------------------------------------------------- 1 | 2 | T=int(input()) 3 | 4 | for tt in range(1,T+1): 5 | 6 | Rs, Rh = [int(x) for x in input().split()] 7 | N = int(input()) 8 | stones = [] 9 | for i in range(N): 10 | X, Y = [int(x) for x in input().split()] 11 | stones.append([X, Y, 0, X**2 + Y**2]) 12 | 13 | M = int(input()) 14 | for i in range(M): 15 | X, Y = [int(x) for x in input().split()] 16 | stones.append([X, Y, 1, X**2 + Y**2]) 17 | 18 | stones.sort(key=lambda x: x[3]) 19 | scores = [0, 0] 20 | if len(stones)>0: 21 | color = stones[0][2] 22 | maxR = (Rs + Rh)**2 23 | for stone in stones: 24 | if stone[2] != color or stone[3] > maxR: 25 | break 26 | else: 27 | scores[stone[2]] += 1 28 | 29 | 30 | print("Case #"+str(tt)+": "+str(scores[0])+" "+str(scores[1])) 31 | 32 | 33 | -------------------------------------------------------------------------------- /2022_RoundG/Walktober.py: -------------------------------------------------------------------------------- 1 | T=int(input()) 2 | 3 | for tt in range(1,T+1): 4 | M, N, P = [int(x) for x in input().split()] 5 | max_steps = [0 for x in range(N)] 6 | my_steps = [] 7 | for i in range(M): 8 | personal_steps = [int(x) for x in input().split()] 9 | for j in range(N): 10 | max_steps[j] = max(max_steps[j], personal_steps[j]) 11 | if i == P-1: 12 | my_steps = personal_steps 13 | 14 | result = 0 15 | for i in range(N): 16 | result += max_steps[i] - my_steps[i] 17 | 18 | 19 | print("Case #"+str(tt)+": "+str(result)) 20 | 21 | 22 | -------------------------------------------------------------------------------- /2022_RoundG/happySubarrays.py: -------------------------------------------------------------------------------- 1 | 2 | T=int(input()) 3 | 4 | for tt in range(1,T+1): 5 | N = int(input()) 6 | numbers = [int(x) for x in input().split()] 7 | prefix = [0] 8 | for number in numbers: 9 | prefix.append(prefix[-1] + number) 10 | prefix_prefix = [0] 11 | for i in range(1, N+1): 12 | prefix_prefix.append(prefix_prefix[-1] + prefix[i]) 13 | 14 | nearest_smaller_value = [N+1 for x in range(N+2)] 15 | stack_bigger_indices = [] 16 | for index in range(N+1): 17 | while stack_bigger_indices and prefix[stack_bigger_indices[-1]] > prefix[index]: 18 | old_index = stack_bigger_indices.pop() 19 | nearest_smaller_value[old_index + 1] = index 20 | stack_bigger_indices.append(index) 21 | 22 | result = 0 23 | for start_pos in range(1, N+1): 24 | right_bound = nearest_smaller_value[start_pos] - 1 25 | if right_bound < start_pos: 26 | continue 27 | result += prefix_prefix[right_bound] - prefix_prefix[start_pos - 1] - (right_bound - start_pos + 1) * prefix[start_pos - 1] 28 | 29 | print("Case #"+str(tt)+": "+str(result)) 30 | 31 | 32 | -------------------------------------------------------------------------------- /2022_RoundH/Electricity.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | using namespace std; 16 | 17 | typedef long long ll; 18 | long long N, E; 19 | long long A[200005]; 20 | long long seen[200005]; 21 | long long dp[200005]; 22 | 23 | long long dfs(int u,vector> & graph ){ 24 | if(seen[u] != 0 ){ 25 | return dp[u]; 26 | } 27 | seen[u] = 1; 28 | long long me = 0; 29 | for(int neighbor: graph[u]){ 30 | if(A[neighbor] < A[u]){ 31 | me += dfs(neighbor, graph); 32 | } 33 | } 34 | me += 1; 35 | dp[u] = me; 36 | return me; 37 | } 38 | 39 | int main() 40 | { 41 | int t; 42 | cin>>t; 43 | for(int ca=1;ca<=t;ca++) 44 | { 45 | cin>>N; 46 | for(int i=0;i>A[i]; 48 | } 49 | vector> graph(N, vector()); 50 | memset(seen, 0, sizeof seen); 51 | int X, Y; 52 | for(int i=0;i>X>>Y; 54 | X--; 55 | Y--; 56 | graph[X].push_back(Y); 57 | graph[Y].push_back(X); 58 | } 59 | 60 | for(int i=0; i L: 14 | break 15 | dp[target] = min(dp[target], dp[i] + 4 + 2*(multiplier-1)) 16 | 17 | print("Case #"+str(tt)+": "+str(dp[L])) 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /2022_RoundH/runningInCircles.py: -------------------------------------------------------------------------------- 1 | import math 2 | T=int(input()) 3 | 4 | for tt in range(1,T+1): 5 | # offset is the offset regarding starting line based on current direction 6 | offset = 0 7 | # prev is the previous direction of the run 8 | prev = 0 9 | # direction when last passed starting line 10 | lap_direction = 0 11 | result = 0 12 | L, N = [int(x) for x in input().split()] 13 | for i in range(N): 14 | distance, direction = input().split() 15 | distance = int(distance) 16 | if i == 0: 17 | lap_direction = direction 18 | laps = math.floor(distance / L) 19 | result += laps 20 | offset = distance % L 21 | prev = direction 22 | continue 23 | 24 | if direction == prev: 25 | offset += distance 26 | if offset < L: 27 | prev = direction 28 | elif offset >= L: 29 | laps = math.floor(offset / L) 30 | result += laps 31 | if direction != lap_direction: 32 | result -= 1 33 | lap_direction = direction 34 | offset = offset % L 35 | prev = direction 36 | else: 37 | if distance < offset: 38 | complement = offset - distance 39 | offset = L - complement 40 | prev = direction 41 | elif distance >= offset: 42 | distance -= offset 43 | prev = direction 44 | if direction == lap_direction: 45 | result += 1 46 | lap_direction = direction 47 | offset = distance 48 | result += math.floor(offset / L) 49 | offset = offset % L 50 | 51 | print("Case #"+str(tt)+": "+str(result)) 52 | 53 | 54 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Update 07/07/2023: 2 | [All Google coding competitions have come to an end](https://developers.googleblog.com/2023/05/celebrate-googles-coding-competitions.html) Very sad news indeed. Hope everyone still loves competitive coding and keeps on learning, practicing, and achieving! 3 | 4 | My AC solutions that passes **\*\*ALL\*\*** test cases, with explanations.
5 | **\*\*EVERY\*\*** problem before 2017_Round C and after 2017_round F.

6 | 7 | 1. Some problem analysis provides **unique** approaches that I haven't seen other people use e.g. 2020 round d problem 4
8 | 3. Some problem analysis provides my approach that is easier to implement than, and equally as good as the official solution e.g. 2021 round f problem 2
9 | 3. Some problem analysis (written by me) are the most detailed analysis on the internet (because no one writes about it :) e.g. 2016 round e problem 4)
10 | 4. Some problem analysis corrects mistakes made in official analysis. i.e., you would get **WRONG** answer if you follow the implementation of official analysis. See why the official analysis is wrong in e.g. 2022 Round H problem 4. (as of 11/15/2022)

11 | 12 | I have re-named my variables and functions to be more verbose in my solutions to increase readability of codes.
13 | --------------------------------------------------------------------------------