how can I produce a query which would result in column names like the
  following without writing them into the query:
Even with crosstab() (from the tablefunc extension), you have to spell out the column names.
Except, if you create a dedicated C function for your query. The tablefunc extension provides a framework for this, output columns (the list of countries) have to be stable, though. I wrote up a "tutorial" for a similar case a few days ago:
The alternative is to use CASE statements like this:
SELECT sum(CASE WHEN t.id = 1 THEN o.ct END) AS "Singapore"
     , sum(CASE WHEN t.id = 2 THEN o.ct END) AS "Vancouver"
     , sum(CASE WHEN t.id = 3 THEN o.ct END) AS "Egypt"
       -- more?
FROM   tbl t
JOIN  (
    SELECT id, count(*) AS ct
    FROM   other_tbl
    GROUP  BY id
    ) o USING (id);
ELSE NULL is optional in a CASE expression. The manual:
If the ELSE clause is omitted and no condition is true, the result is null.
Basics for both techniques: