Haskell
Found the tree using visual inspection.
import Data.Array
solve1 (w,h) xs = safety (w,h) $ map (robot (w,h) 100) xs
safety (w,h) xs = q1 * q2 * q3 * q4
where q1 = length $ filter (\(x,y) -> x < w1 && y < h1) xs
q2 = length $ filter (\(x,y) -> x > w1 && y < h1) xs
q3 = length $ filter (\(x,y) -> x < w1 && y > h1) xs
q4 = length $ filter (\(x,y) -> x > w1 && y > h1) xs
w1 = w `div` 2
h1 = h `div` 2
robot (w,h) n ((px,py),(vx,vy)) = ((px + vx*n) `mod` w, (py + vy*n) `mod` h)
solve2 (w,h) xs = mapM (\i -> writeFile (show i ++ ".pbm") $ bitmap (w,h) $ map (robot (w,h) i) xs) [0..10_000]
bitmap (w,h) xs = "P1\n" ++ show h ++ " " ++ show w ++ "\n" ++ elems a
where a = listArray ((0,0),(w-1,h-1)) (repeat '0') // zip xs (repeat '1')
readRobot :: String -> ((Int,Int),(Int,Int))
readRobot xs = (pair x, pair y)
where pair ys = read $ "(" ++ drop 2 ys ++ ")"
[x,y] = words xs
main = do xs <- map readRobot . lines <$> readFile "input"
print $ solve1 (101,103) xs
solve2 (101,103) xs