cppAcademy
FROM LEARNING TO COMPETING

Proficient.
Put your skills to the test.

Bulgarian Informatics Group B · 2009–2026

217 independently explained problems: 54 Municipal, 54 Regional and 109 National. Start with the easier tasks and work upwards. Difficulty labels are learning estimates, not official ratings; Group B also includes challenging national-level problems. National-round tasks shared by Groups A and B are included. Years follow Arena’s competition-season labels. Source clarifications and special grader requirements are noted on affected tasks.
GROUP B2014 · MediumBitsets

Singers and Shared Songs

National Olympiad — Regional round (2014 season)

Submission name: singers.cpp

Problem summary

Student 1 creates a new song whenever he attends a contest; only that new song is sung there. At a contest without him, attendees sing and learn the union of all songs they already know. Find which other students know every song by the end.

Input

M N, then M chronological attendance lists, each beginning with its length B.

Output

The count of qualifying colleagues, then their increasing IDs on the next line; if none qualify, print only 0. Student 1 is not a colleague in this output.

Constraints

3≤M≤2000; 5≤N≤2000; 2≤B≤N/2.

Worked example

An independently prepared example for this explanation.

Input

3 6
3 1 2 3
3 4 1 5
2 2 4

Output

2
2 4

Solution analysis

  1. Represent each student’s known songs by a bitset with one bit per contest. When student 1 attends, assign a new bit and set it for every attendee; earlier songs are not exchanged on that occasion.
  2. When student 1 is absent, OR together all attendee bitsets, then OR the resulting union into every attendee. A final bitset records every created song; compare each student numbered 2 through N with it.
  3. The sample creates song one for students 1,2,3 and song two for 1,4,5. At the last contest, 2 and 4 exchange their songs, so those two colleagues know both. Student 1 is excluded from the requested list.

Why it works

Initially all knowledge sets are empty. A contest with the songwriter adds exactly its one new song to attendees. A contest without him makes precisely the attendees’ union known to each attendee. The bitset operations implement these rules exactly, so induction over chronological contests proves the final sets correct.

Complexity: O((Σ B)·ceil(M/64)+N·ceil(M/64)) time and O(N·ceil(M/64)) 64-bit words of space.

Watch out. Do not spread old songs at a contest with student 1. Student 1 is excluded. If no songs were created, every colleague vacuously knows all songs.

Commented C++17 solution

An independently written complete program with standard headers.

#include<iostream>
#include<vector>
#include<cstdint>
#include<algorithm>
// Algorithm: Represent each student’s known songs by a bitset with one bit per contest.
using namespace std;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int contests,students;
    cin>>contests>>students;
    int words=(contests+63)/64;
    vector<vector<uint64_t>>known(students+1,vector<uint64_t>(words,0));
    vector<uint64_t>allSongs(words,0);
    int songs=0;
    for(int event=0;event<contests;event++){
        int count;
        cin>>count;
        vector<int>attendees(count);
        bool songwriter=false;
        for(int&student:attendees){
            cin>>student;
            songwriter=songwriter||student==1;
        }
        if(songwriter){
            int word=songs/64;
            uint64_t bit=uint64_t(1)<<(songs%64);
            songs++;
            allSongs[word]|=bit;
            for(int student:attendees){
                known[student][word]|=bit;
            }
        }
        else{
            vector<uint64_t>shared(words,0);
            for(int student:attendees){
                for(int w=0;w<words;w++){
                    shared[w]|=known[student][w];
                }
            }
            for(int student:attendees){
                for(int w=0;w<words;w++){
                    known[student][w]|=shared[w];
                }
            }
        }
    }
    vector<int>answer;
    for(int student=2;student<=students;student++){
        if(known[student]==allSongs){
            answer.push_back(student);
        }
    }
    cout<<answer.size()<<'\n';
    if(!answer.empty()){
        for(size_t i=0;i<answer.size();i++){
            if(i!=0){
                cout<<' ';
            }
            cout<<answer[i];
        }
        cout<<'\n';
    }
}

Source: Arena Olimpiici ↗