Problem:
Problem E:
Frisbee Dogs
クレインは, 彼女の愛犬である Jack をフリスビードッグ大会に出場させようとしている. しかし, 彼女は Jack がよい成績を取れるか自信が無い. 彼女のために, 大会をシミュレートして Jack の成績を見積もるプログラムを作成してほしい.
この大会は, 2次元平面上にいる N 匹の犬によって行われる. 大会の開始時点において,
i
番目の犬は (
D
i
x
,
D
i
y
) の位置にいる.
i
番目の犬は
V
i
[m/s] で走ることができ, 全ての犬は十分小さいので点とみなせる. ある時刻に, 2 匹以上の犬が同じ位置にいても構わない.
1枚目のフリスビーの発射をもって大会は開始し, この瞬間から犬たちは動くことを許される. フリスビーもまた点とみなすことができ,
i
枚目のフリスビーは (
FP
i
x
,
FP
i
y
) の位置から (
FV
i
x
,
FV
i
y
) [m/s] の速度ベクトルで発射され, 等速直線運動を続ける. ある犬の位置とフリスビーの位置が等しくなったとき, その犬はフリスビーを取得することができる.
1枚目のフリスビーがいずれかの犬に取得された瞬間, 2枚目のフリスビーが発射される. 2枚目のフリスビーが取得された瞬間3枚目が発射され, 以下同様にフリスビーが取得された直後に次のフリスビーが発射される. M 枚目のフリスビーが取得されると大会は終了する.
言うまでもなく, 犬たちの目標はより多くのフリスビーを取得することである. 犬たちは, 以下のような戦略をとる.
フリスビーが発射されたとき, 犬は可能な限り早い時刻にそれを取得できるように移動し, フリスビーを取得する. ただし, フリスビーを取得できないときは現在いる場所に待機する.
ある犬がフリスビーを取得できるかどうかの判断は, 他の犬の行動に関係なく行われる. つまり, ある犬がフリスビーを取得するために移動したものの, 他の犬に先に取得されてしまうことも有りえる. いずれかの犬がフリスビーを取得し新たなフリスビーが発射された瞬間, 犬たちは新しいフリスビーに対して上記の戦略をとる.
あなたの作成するプログラムは、それぞれの犬が取得したフリスビーの数を出力しなければならない.
Input
入力ファイルは, 複数のデータセットから構成される.
データセットの1行目には, 犬の数 N (1 ≤ N ≤ 10) とフリスビーの数 M (1 ≤ M ≤ 1000)が与えられる.
続く N 行には, 犬の初期位置と速度
D
i
x
,
D
i
y
,
V
i
が1つの空白区切りで与えられる.
続く M 行には, フリスビーの発射位置と速度
FP
i
x
,
FP
i
y
,
FV
i
x
,
FV
i
y
が1つの空白文字区切りで与えられる.
与えられる座標値は実数であり、その絶対値は 1000 を越えない. 与えられる速度は実数であり 1 ≤
DV
i
≤ 100, -25 ≤
FV
i
x
,
FV
i
y
≤ 25 である. どの犬にも取得できないフリスビーはないと仮定してよい.
任意のフリスビーがある犬に時刻
t
で取得されたとき、時刻
t
+ 1e-6 以前にそれを取得できる犬はいない.
シミュレーションの間, 犬の
x
座標,
y
座標の絶対値は 1e+8 を越えない.
N, M がともに 0 のとき入力の終わりを示す.
Output
それぞれの犬が取得したフリスビーの数を, 空白文字で区切って1行に出力せよ. 出力する順番は, 入力で与えられた順番と等しくなければならない.
Sample Input
2 1
12 5 3
0 17 3
0 0 2 2
2 3
2 0 2
100 100 2
0 0 -1 0
-2 -5 0 3
100 100 1 1
0 0
Output for the Sample Input
1 0
2 1

Submitted solutions:

code_snippet: #ifndef HIDDEN_IN_VS // 折りたたみ用

// 警告の抑制
#define _CRT_SECURE_NO_WARNINGS

// ライブラリの読み込み
#include <bits/stdc++.h>
using namespace std;

// 型名の短縮
using ll = long long; // -2^63 ～ 2^63 = 9 * 10^18（int は -2^31 ～ 2^31 = 2 * 10^9）
using pii = pair<int, int>;	using pll = pair<ll, ll>;	using pil = pair<int, ll>;	using pli = pair<ll, int>;
using vi = vector<int>;		using vvi = vector<vi>;		using vvvi = vector<vvi>;
using vl = vector<ll>;		using vvl = vector<vl>;		using vvvl = vector<vvl>;
using vb = vector<bool>;	using vvb = vector<vb>;		using vvvb = vector<vvb>;
using vc = vector<char>;	using vvc = vector<vc>;		using vvvc = vector<vvc>;
using vd = vector<double>;	using vvd = vector<vd>;		using vvvd = vector<vvd>;
template <class T> using priority_queue_rev = priority_queue<T, vector<T>, greater<T>>;
using Graph = vvi;

// 定数の定義
const double PI = acos(-1);
const vi DX = { 1, 0, -1, 0 }; // 4 近傍（下，右，上，左）
const vi DY = { 0, 1, 0, -1 };
int INF = 1001001001; ll INFL = 4004004004004004004LL;
double EPS = 1e-12;

// 入出力高速化
struct fast_io { fast_io() { cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(18); } } fastIOtmp;

// 汎用マクロの定義
#define all(a) (a).begin(), (a).end()
#define sz(x) ((int)(x).size())
#define lbpos(a, x) (int)distance((a).begin(), std::lower_bound(all(a), x))
#define ubpos(a, x) (int)distance((a).begin(), std::upper_bound(all(a), x))
#define Yes(b) {cout << ((b) ? "Yes\n" : "No\n");}
#define rep(i, n) for(int i = 0, i##_len = int(n); i < i##_len; ++i) // 0 から n-1 まで昇順
#define repi(i, s, t) for(int i = int(s), i##_end = int(t); i <= i##_end; ++i) // s から t まで昇順
#define repir(i, s, t) for(int i = int(s), i##_end = int(t); i >= i##_end; --i) // s から t まで降順
#define repe(v, a) for(const auto& v : (a)) // a の全要素（変更不可能）
#define repea(v, a) for(auto& v : (a)) // a の全要素（変更可能）
#define repb(set, d) for(int set = 0; set < (1 << int(d)); ++set) // d ビット全探索（昇順）
#define repp(a) sort(all(a)); for(bool a##_perm = true; a##_perm; a##_perm = next_permutation(all(a))) // a の順列全て（昇順）
#define smod(n, m) ((((n) % (m)) + (m)) % (m)) // 非負mod
#define uniq(a) {sort(all(a)); (a).erase(unique(all(a)), (a).end());} // 重複除去
#define EXIT(a) {cout << (a) << endl; exit(0);} // 強制終了

// 汎用関数の定義
template <class T> inline ll pow(T n, int k) { ll v = 1; rep(i, k) v *= n; return v; }
template <class T> inline bool chmax(T& M, const T& x) { if (M < x) { M = x; return true; } return false; } // 最大値を更新（更新されたら true を返す）
template <class T> inline bool chmin(T& m, const T& x) { if (m > x) { m = x; return true; } return false; } // 最小値を更新（更新されたら true を返す）

// 演算子オーバーロード
template <class T, class U> inline istream& operator>>(istream& is, pair<T, U>& p) { is >> p.first >> p.second; return is; }
template <class T> inline istream& operator>>(istream& is, vector<T>& v) { repea(x, v) is >> x; return is; }
template <class T> inline vector<T>& operator--(vector<T>& v) { repea(x, v) --x; return v; }
template <class T> inline vector<T>& operator++(vector<T>& v) { repea(x, v) ++x; return v; }

// 手元環境（Visual Studio）
#ifdef _MSC_VER
#include "local.hpp"
// 提出用（gcc）
#else
inline int popcount(int n) { return __builtin_popcount(n); }
inline int popcount(ll n) { return __builtin_popcountll(n); }
inline int lsb(int n) { return n != 0 ? __builtin_ctz(n) : -1; }
inline int lsb(ll n) { return n != 0 ? __builtin_ctzll(n) : -1; }
inline int msb(int n) { return n != 0 ? (31 - __builtin_clz(n)) : -1; }
inline int msb(ll n) { return n != 0 ? (63 - __builtin_clzll(n)) : -1; }
#define gcd __gcd
#define dump(...)
#define dumpel(v)
#define dump_list(v)
#define input_from_file(f)
#define output_to_file(f)
#define Assert(b) { if (!(b)) while (1) cout << "OLE"; }
#endif

#endif // 折りたたみ用


////--------------AtCoder 専用--------------
//#include <atcoder/all>
//using namespace atcoder;
//
////using mint = modint1000000007;
//using mint = modint998244353;
////using mint = modint; // mint::set_mod(m);
//
//istream& operator>>(istream& is, mint& x) { ll x_; is >> x_; x = x_; return is; }
//ostream& operator<<(ostream& os, const mint& x) { os << x.val(); return os; }
//using vm = vector<mint>; using vvm = vector<vm>; using vvvm = vector<vvm>;
////----------------------------------------


//【平面上の点，二次元ベクトル】
/*
* 平面における点／二次元ベクトルを表す構造体
*
* Point<T>() : O(1)
*	(0, 0) で初期化する．
*
* Point<T>(T x, T y) : O(1)
*	(x, y) で初期化する．
*
* p1 == p2, p1 != p2, p1 < p2, p1 > p2, p1 <= p2, p1 >= p2 : O(1)
*	x 座標優先，次いで y 座標の大小比較を行う．
*
* p1 + p2, p1 - p2, c * p, p * c, p / c : O(1)
*	ベクトルとみなした加算，減算，スカラー倍，スカラー除算を行う．複合代入演算子も使用可．
*
* T sqnorm() : O(1)
*	自身の 2 乗ノルムを返す．
*
* double norm() : O(1)
*	自身のノルムを返す．
*
* Point<double> normalize() : O(1)
*	自身を正規化したベクトルを返す．
*
* T dot(Point<T> p) : O(1)
*	自身と p との内積を返す．
*
* T cross(Point<T> p) : O(1)
*	自身と p との外積を返す．
*
* double angle(Point<T> p) : O(1)
*	自身から p までの成す角度を返す．
*/
template <class T> struct Point {
	// 点の x 座標，y 座標
	T x, y;

	// コンストラクタ
	Point() : x(0), y(0) {}
	Point(T x_, T y_) : x(x_), y(y_) {}

	// 代入
	Point(const Point& old) = default;
	Point& operator=(const Point& other) = default;

	// キャスト
	operator Point<ll>() const { return Point<ll>((ll)x, (ll)y); }
	operator Point<double>() const { return Point<double>((double)x, (double)y); }

	// 入出力
	friend istream& operator>>(istream& is, Point& p) { is >> p.x >> p.y; return is; }
	friend ostream& operator<<(ostream& os, const Point& p) { os << '(' << p.x << ',' << p.y << ')'; return os; }

	// 比較（x 座標優先）
	bool operator==(const Point& p) const { return x == p.x && y == p.y; }
	bool operator!=(const Point& p) const { return !(*this == p); }
	bool operator<(const Point& p) const { return x == p.x ? y < p.y : x < p.x; }
	bool operator>=(const Point& p) const { return !(*this < p); }
	bool operator>(const Point& p) const { return x == p.x ? y > p.y : x > p.x; }
	bool operator<=(const Point& p) const { return !(*this > p); }

	// 加算，減算，スカラー倍，スカラー除算
	Point& operator+=(const Point& p) { x += p.x; y += p.y;	return *this; }
	Point operator+(const Point& p) const { Point q(*this); return q += p; }
	Point& operator-=(const Point& p) { x -= p.x; y -= p.y;	return *this; }
	Point operator-(const Point& p) const { Point q(*this); return q -= p; }
	Point& operator*=(const T& c) { x *= c; y *= c;	return *this; }
	Point operator*(const T& c) const { Point q(*this); return q *= c; }
	Point& operator/=(const T& c) { x /= c; y /= c;	return *this; }
	Point operator/(const T& c) const { Point q(*this); return q /= c; }
	friend Point operator*(const T& sc, const Point& p) { return p * sc; }
	Point operator-() const { Point a = *this; return a *= -1; }

	// 二乗ノルム，ノルム，正規化
	T sqnorm() const { return x * x + y * y; }
	double norm() const { return sqrt((double)x * x + (double)y * y); }
	Point<double> normalize() const { return Point<double>(*this) / norm(); }

	// 内積，外積，成す角度
	T dot(const Point& other) const { return x * other.x + y * other.y; }
	T cross(const Point& other) const { return x * other.y - y * other.x; }
	double angle(const Point& other) const {
		return atan2(this->cross(other), this->dot(other));
	}
};


//【黄金分割探索（実数，下に凸）】O(log((right - left) / EPS))
/*
* 全域で狭義に下に凸な関数 f(x) の開区間 (left, right) における最小値を与える x を返す．
*/
double golden_search_lc(double left, double right, function<double(double)>& f) {
	// verify : https://atcoder.jp/contests/arc049/tasks/arc049_b

	const double phi = (1 + sqrt(5)) / 2;

	// l, m1, m2, r の順で区間を φ: 1 :φ に内分する点
	double l = left;
	double r = right;
	double m1 = (l * (1 + phi) + r * phi) / (2 * phi + 1);
	double m2 = (l * phi + r * (1 + phi)) / (2 * phi + 1);

	// 内分点における関数値の計算
	double v1 = f(m1);
	double v2 = f(m2);

	// 絶対誤差か相対誤差が EPS 以下になるまで
	while (r - l > EPS && r - l > EPS * (r + l) / 2) {
		// 左の内分点での値の方が小さければ，次の区間は左側をとる．
		if (v1 < v2) {
			// 右の内分点を新たに右端とする．
			r = m2;

			// 左の内分点を新たに右の内分点とする．
			m2 = m1;
			v2 = v1;

			// 左の内分点を新たに計算する．
			m1 = (l * (1 + phi) + r * phi) / (2 * phi + 1);
			v1 = f(m1);
		}
		// 右の内分点での値の方が小さければ，次の区間は右側をとる．
		else {
			// 左の内分点を新たに左端とする．
			l = m1;

			// 右の内分点を新たに左の内分点とする．
			m1 = m2;
			v1 = v2;

			// 右の内分点を新たに計算する．
			m2 = (l * phi + r * (1 + phi)) / (2 * phi + 1);
			v2 = f(m2);
		}
	}

	// 最後の候補を比較し，小さかった方の x を返す．
	return (v1 < v2) ? m1 : m2;

	/* f の定義の雛形
	function<double(double)> f = [&](double x) {
		return x;
	};
	*/
}


//【二分探索（実数）】O(log(|ok - ng| / EPS))
/*
* 条件 okQ() を満たす要素 ok と満たさない要素 ng との境界を二分探索する．
*/
template <typename T> T binary_search(T ok, T ng, function<bool(T)>& okQ) {
	// verify : https://atcoder.jp/contests/abc189/tasks/abc189_f

	// 誤差 EPS で境界が決定するまで
	while (true) {
		// 区間の中間
		T mid = (ok + ng) / 2;
		//double mid = sqrt(ok * ng); // 相対誤差を小さくする場合

		// 絶対誤差か相対誤差が EPS 以下なら終了する．
		T err = abs(ok - ng);
		if (err <= EPS || err <= abs(mid) * EPS) {
			break;
		}

		// 中間が OK かどうかに応じて区間を縮小する．
		if (okQ(mid)) ok = mid;
		else ng = mid;
	}
	return (ok + ng) / 2;

	/* okQ の定義の雛形
	function<bool(double)> okQ = [&](double x) {
		return true || false;
	};
	*/
}


void solve() {
	int n, m;
	cin >> n >> m;

	if (n == 0) exit(0);

	vector<Point<double>> dp(n); vd dv(n);
	rep(i, n) cin >> dp[i] >> dv[i];

	vector<Point<double>> fp(m), fv(m);
	rep(j, m) cin >> fp[j] >> fv[j];

	dump(dp); dump(dv); dump(fp); dump(fv);

	vi res(n);

	rep(j, m) {
		dump("----", j, "----");
		vb moveQ(n);
		vector<Point<double>> d_dir(n);
		double t_min = (double)INF; int i_min = -1;

		rep(i, n) {
			function<double(double)> f = [&](double t) {
				auto nfp = fp[j] + t * fv[j];
				double f_dist = (nfp - dp[i]).norm();
				return f_dist / dv[i] - t;
			};

			double t_ub = golden_search_lc(0., (double)INF, f);
			dump(t_ub);

			auto nfp = fp[j] + t_ub * fv[j];
			double f_dist = (nfp - dp[i]).norm();

			if (f_dist / dv[i] - t_ub <= 1e-6) {
				function<bool(double)> okQ = [&](double t) {
					auto nfp = fp[j] + t * fv[j];
					double f_dist = (nfp - dp[i]).norm();
					return f_dist / dv[i] - t >= 0;
				};

				double t0 = binary_search(0., t_ub, okQ);
				dump(t0);

				auto nfp = fp[j] + t0 * fv[j];

				moveQ[i] = true;
				d_dir[i] = (nfp - dp[i]).normalize();
				if (chmin(t_min, t0)) i_min = i;
			}
		}
		dump(moveQ); dump(d_dir); dump(t_min); dump(i_min);

		rep(i, n) {
			if (!moveQ[i]) continue;

			dp[i] += d_dir[i] * dv[i] * t_min;
		}

		res[i_min]++;
	}

	rep(i, n) cout << res[i] << (i < n - 1 ? " " : "\n");
}


int main() {
//	input_from_file("input.txt");
//	output_to_file("output.txt");
	
	while (true) {
		solve();
	}
}
accuracy: 1
time_ms: 770
memory_kb: 3544
final_rank: 19

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 1000000000000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 12

struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{
		return x != p.x? x < p.x: y < p.y;
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}

   	/*
	void debug(){

		printf("(%.3lf,%.3lf)\n",x,y);
	}*/

	double x,y;
};

typedef Point Vector;

struct Info{

	double dx,dy;
};

int num_dog,M;
int ans[SIZE];
double V[SIZE],need_time[SIZE];
Point point[SIZE];
Vector vec[SIZE];


double calc_dist(Point A,Point B){

	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}

double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}


void func(){

	for(int i = 0; i < num_dog; i++){

		scanf("%lf %lf %lf",&point[i].x,&point[i].y,&V[i]);
		ans[i] = 0;
	}

	Point loc;
	Vector tmp_v;

	double A,B,C,D;

	for(int i = 0; i < M; i++){

		scanf("%lf %lf %lf %lf",&loc.x,&loc.y,&tmp_v.x,&tmp_v.y);

		for(int k = 0; k < num_dog; k++){

			if(point[k] == loc){

				need_time[k] = 0;
				vec[k] = Vector(0,0);
				continue;
			}

			need_time[k] = DBL_MAX;

			A = norm(tmp_v)-V[k]*V[k];
			B = 2*dot(tmp_v,loc-point[k]);
			C = norm(loc-point[k]);

			if(fabs(A) > EPS){

				D = B*B-4*A*C;

				if(D >= 0){

					if((-B+sqrt(D))/(2*A) >= 0){ //★★負の時間は不可★★

						need_time[k] = (-B+sqrt(D))/(2*A);
					}
					if((-B-sqrt(D))/(2*A) >= 0){

						need_time[k] = min(need_time[k],(-B-sqrt(D))/(2*A));
					}
				}
			}else if(fabs(B) > EPS){

				if(-C/(2*B) >= 0){

					need_time[k] = -C/(2*B);
				}
			}

			if(fabs(need_time[k]-DBL_MAX) < EPS){ //その場にとどまる

				vec[k] = Vector(0,0);

			}else{

				Point tmp_p = loc+tmp_v*need_time[k];
				vec[k] = tmp_p - point[k];
				vec[k] = vec[k]/abs(vec[k]); //★★単位ベクトルにする★★
			}
		}

		double min_T = DBL_MAX;
		int min_index;

		for(int k = 0; k < num_dog; k++){

			if(need_time[k]+EPS < min_T){
				min_T = need_time[k];
				min_index = k;
			}
		}

		ans[min_index]++;

		for(int k = 0; k < num_dog; k++){

			point[k] = point[k]+vec[k]*min_T*V[k]; //★★注意★★
		}
	}

	printf("%d",ans[0]);
	for(int i = 1; i < num_dog; i++){

		printf(" %d",ans[i]);
	}
	printf("\n");
}

int main(){

	while(true){

		scanf("%d %d",&num_dog,&M);
		if(num_dog == 0 && M == 0)break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 3216
final_rank: 6

code_snippet: #include <algorithm>
#include <cmath>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <set>
#include <tuple>
#include <vector>

using namespace std;

#define rep(i, n) for (int64_t i = 0; i < (n); i++)
#define irep(i, n) for (int64_t i = 0; i <= (n); i++)
#define rrep(i, n) for (int64_t i = (n)-1; i >= 0; i--)
#define rirep(i, n) for (int64_t i = n; i >= 0; i--)

class Vec;
Vec operator/(const Vec& v, const double& divisor);
Vec operator*(const double& scale, const Vec& v);

class Vec {
  using F = double;
  vector<F> container;

 public:
  explicit Vec(size_t size) : container(size) {}
  explicit Vec(initializer_list<F> elements)
      : container(elements.begin(), elements.end()) {}
  size_t dim() const { return container.size(); }
  F& operator[](const size_t size) { return container.at(size); }
  const F& operator[](const size_t size) const { return container.at(size); }
  Vec operator+(const Vec& other) const {
    Vec ret(*this);
    for (size_t i = 0; i < dim(); i++) ret[i] += other[i];
    return ret;
  }
  Vec operator-(const Vec& other) const { return (*this) + (-other); }
  Vec operator-() const { return -1.0 * (*this); }
  F inner(const Vec& other) const {
    F acc = 0;
    for (size_t i = 0; i < dim(); i++) {
      acc += (*this)[i] * other[i];
    }
    return acc;
  }
  Vec& operator+=(const Vec& other) {
    for (size_t i = 0; i < dim(); i++) {
      (*this)[i] += other[i];
    }
    return *this;
  }
  F norm() const { return sqrt(inner(*this)); }
  Vec unit() const { return (*this) / this->norm(); }
  F ccw(const Vec& other) const {
    return (*this)[0] * other[1] - other[0] * (*this)[1];
  }
  Vec normal() const { return Vec({-(*this)[1], (*this)[0]}); }
};
Vec operator/(const Vec& v, const double& divisor) { return 1.0 / divisor * v; }
Vec operator*(const double& scale, const Vec& v) {
  Vec ret(v);
  for (size_t i = 0; i < ret.dim(); i++) ret[i] *= scale;
  return ret;
}

pair<vector<double>, bool> solve_linear(double a, double b, double eps);
pair<vector<double>, bool> solve_quad(double a, double b, double c, double eps);
vector<double> solve_quad(double a, double b, double eps);

/// solve ax+b=0
pair<vector<double>, bool> solve_linear(double a, double b, double eps) {
  vector<double> sol;
  if (abs(a) > eps) {
    sol.push_back(-b / a);
    return make_pair(sol, false);
  } else if (abs(b) > eps) {
    return make_pair(sol, false);
  } else {
    return make_pair(sol, true);
  }
}

/// solve ax^2+bx+c=0
pair<vector<double>, bool> solve_quad(double a, double b, double c,
                                      double eps) {
  if (abs(a) > eps) {
    return make_pair(solve_quad(b / a, c / a, eps), false);
  } else {
    return solve_linear(b, c, eps);
  }
}

/// solve x^2+ax+b=0
vector<double> solve_quad(double a, double b, double eps) {
  double det = a * a - 4 * b;
  vector<double> result;
  if (!(det < 0)) {
    if (det < eps) {
      result.push_back(-a / 2);
    } else {
      const double r = sqrt(det) / 2;
      result.push_back(-a / 2 - r);
      result.push_back(-a / 2 + r);
    }
  }

  return result;
}

void solve(int N, int M) {
  vector<Vec> dog;
  vector<double> dogv;
  rep(i, N) {
    double x, y, v;
    cin >> x >> y >> v;
    dog.push_back(Vec({x, y}));
    dogv.push_back(v);
  }

  vector<int> cnt(N, 0);
  rep(i, M) {
    double x, y, ux, uy;
    cin >> x >> y >> ux >> uy;
    Vec p({x, y}), u({ux, uy});

    int j;
    double t = numeric_limits<double>::max();

    vector<Vec> v;
    rep(i, N) {
      const Vec d = p - dog[i];
      const double EPS = 1e-9;
      vector<double> sol;
      bool eq;
      tie(sol, eq) = solve_quad(u.norm() * u.norm() - dogv[i] * dogv[i],
                                2 * d.inner(u), d.norm() * d.norm(), EPS);
      if (eq) {
        t = 0;
        j = i;
        v.push_back(Vec({0, 0}));
      } else {
        sol.push_back(numeric_limits<double>::max());
        sort(sol.begin(), sol.end());
        double s =
            *min_element(lower_bound(sol.begin(), sol.end(), 0), sol.end());

        const double INF = 1e9;
        if (s < EPS) {
          v.push_back(Vec({0, 0}));
        } else if (s > INF) {
          v.push_back(Vec({0, 0}));
        } else {
          v.push_back(u + d / s);
        }
        if (t > s) {
          t = s;
          j = i;
        }
      }
    }
    cnt[j]++;
    rep(i, N) { dog[i] += t * v[i]; }
  }

  rep(i, N) {
    cout << cnt[i];
    if (i < N - 1) cout << " ";
  }
  cout << "\n";
}

int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  int N, M;
  cin >> N >> M;
  while (N != 0 || M != 0) {
    solve(N, M);
    cin >> N >> M;
  }
  return 0;
}
accuracy: 1
time_ms: 190
memory_kb: 3324
final_rank: 12

code_snippet: #define _USE_MATH_DEFINES
#include <bits/stdc++.h>
using namespace std;
#define FOR(i,m,n) for(int i=(m);i<(n);++i)
#define REP(i,n) FOR(i,0,n)
#define ALL(v) (v).begin(),(v).end()
using ll = long long;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3fLL;
const double EPS = 1e-8;
const int MOD = 1000000007;
// const int MOD = 998244353;
const int dy[] = {1, 0, -1, 0}, dx[] = {0, -1, 0, 1};
const int dy8[] = {1, 1, 0, -1, -1, -1, 0, 1}, dx8[] = {0, -1, -1, -1, 0, 1, 1, 1};
template <typename T, typename U> inline bool chmax(T &a, U b) { return a < b ? (a = b, true) : false; }
template <typename T, typename U> inline bool chmin(T &a, U b) { return a > b ? (a = b, true) : false; }
struct IOSetup {
  IOSetup() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout << fixed << setprecision(20);
  }
} iosetup;

namespace Geometry {
  using Real = double;

  int sgn(Real x) { return x > EPS ? 1 : x < -EPS ? -1 : 0; }

  Real degree_to_radian(Real d) { return d * M_PI / 180; }
  Real radian_to_degree(Real r) { return r * 180 / M_PI; }

  struct Point {
    Real x, y;
    Point(Real x = 0, Real y = 0) : x(x), y(y) {}
    Real abs() const { return sqrt(norm()); }
    Real arg() const { Real res = atan2(y, x); return res < 0 ? res + M_PI * 2 : res; }
    Real norm() const { return x * x + y * y; }
    Point rotate(Real angle) const { Real cs = cos(angle), sn = sin(angle); return Point(x * cs - y * sn, x * sn + y * cs); }
    Point unit_vector() const { Real a = abs(); return Point(x / a, y / a); }
    pair<Point, Point> normal_unit_vector() const { Point p = unit_vector(); return {Point(-p.y, p.x), Point(p.y, -p.x)}; }
    Point &operator+=(const Point &p) { x += p.x; y += p.y; return *this; }
    Point &operator-=(const Point &p) { x -= p.x; y -= p.y; return *this; }
    Point &operator*=(Real k) { x *= k; y *= k; return *this; }
    Point &operator/=(Real k) { x /= k; y /= k; return *this; }
    bool operator<(const Point &p) const { int x_sgn = sgn(p.x - x); return x_sgn != 0 ? x_sgn == 1 : sgn(p.y - y) == 1; }
    bool operator<=(const Point &p) const { return !(p < *this); }
    bool operator>(const Point &p) const { return p < *this; }
    bool operator>=(const Point &p) const { return !(*this < p); }
    Point operator+() const { return *this; }
    Point operator-() const { return Point(-x, -y); }
    Point operator+(const Point &p) const { return Point(*this) += p; }
    Point operator-(const Point &p) const { return Point(*this) -= p; }
    Point operator*(Real k) const { return Point(*this) *= k; }
    Point operator/(Real k) const { return Point(*this) /= k; }
    friend ostream &operator<<(ostream &os, const Point &p) { return os << '(' << p.x << ", " << p.y << ')'; }
    friend istream &operator>>(istream &is, Point &p) { Real x, y; is >> x >> y; p = Point(x, y); return is; }
  };

  struct Segment {
    Point s, t;
    Segment(const Point &s = {0, 0}, const Point &t = {0, 0}) : s(s), t(t) {}
  };
  struct Line : Segment {
    using Segment::Segment;
    Line(Real a, Real b, Real c) {
      if (sgn(a) == 0) {
        s = Point(0, -c / b); t = Point(1, s.y);
      } else if (sgn(b) == 0) {
        s = Point(-c / a, 0); t = Point(s.x, 1);
      } else if (sgn(c) == 0) {
        s = Point(0, 0); t = Point(1, -a / b);
      } else {
        s = Point(0, -c / b); t = Point(-c / a, 0);
      }
    }
  };

  struct Circle {
    Point p; Real r;
    Circle(const Point &p = {0, 0}, Real r = 0) : p(p), r(r) {}
  };

  Real cross(const Point &a, const Point &b) { return a.x * b.y - a.y * b.x; }
  Real dot(const Point &a, const Point &b) { return a.x * b.x + a.y * b.y; }

  int ccw(const Point &a, const Point &b, const Point &c) {
    Point ab = b - a, ac = c - a;
    int sign = sgn(cross(ab, ac));
    if (sign == 0) {
      if (sgn(dot(ab, ac)) == -1) return 2;
      if (sgn(ac.norm() - ab.norm()) == 1) return -2;
    }
    return sign;
  }

  Real get_angle(const Point &a, const Point &b, const Point &c) {
    Real ba_arg = (a - b).arg(), bc_arg = (c - b).arg();
    if (ba_arg > bc_arg) swap(ba_arg, bc_arg);
    return min(bc_arg - ba_arg, M_PI * 2 - (bc_arg - ba_arg));
  }

  Real closest_pair(vector<Point> ps) {
    int n = ps.size();
    assert(n > 1);
    sort(ALL(ps));
    function<Real(int, int)> rec = [&](int left, int right) {
      int mid = (left + right) >> 1;
      Real x_mid = ps[mid].x, d = LINF;
      if (left + 1 < mid) chmin(d, rec(left, mid));
      if (mid + 1 < right) chmin(d, rec(mid, right));
      inplace_merge(ps.begin() + left, ps.begin() + mid, ps.begin() + right, [&](const Point &a, const Point &b) { return sgn(b.y - a.y) == 1; });
      vector<Point> tmp;
      FOR(i, left, right) {
        if (sgn(abs(ps[i].x - x_mid) - d) == 1) continue;
        for (int j = static_cast<int>(tmp.size()) - 1; j >= 0; --j) {
          Point now = ps[i] - tmp[j];
          if (sgn(now.y - d) == 1) break;
          chmin(d, now.abs());
        }
        tmp.emplace_back(ps[i]);
      }
      return d;
    };
    return rec(0, n);
  }

  Point projection(const Segment &a, const Point &b) { return a.s + (a.t - a.s) * dot(a.t - a.s, b - a.s) / (a.t - a.s).norm(); }
  Point reflection(const Segment &a, const Point &b) { return projection(a, b) * 2 - b; }

  bool is_parallel(const Segment &a, const Segment &b) { return sgn(cross(a.t - a.s, b.t - b.s)) == 0; }
  bool is_orthogonal(const Segment &a, const Segment &b) { return sgn(dot(a.t - a.s, b.t - b.s)) == 0; }

  Real distance(const Point&, const Point&);
  Real distance(const Segment&, const Point&);
  Real distance(const Line&, const Point&);
  int sizeof_common_tangent(const Circle&, const Circle&);
  bool has_intersected(const Segment &a, const Point &b) { return ccw(a.s, a.t, b) == 0; }
  bool has_intersected(const Segment &a, const Segment &b) { return ccw(a.s, a.t, b.s) * ccw(a.s, a.t, b.t) <= 0 && ccw(b.s, b.t, a.s) * ccw(b.s, b.t, a.t) <= 0; }
  bool has_intersected(const Line &a, const Point &b) { int c = ccw(a.s, a.t, b); return c != 1 && c != -1; }
  bool has_intersected(const Line &a, const Segment &b) { return ccw(a.s, a.t, b.s) * ccw(a.s, a.t, b.t) != 1; }
  bool has_intersected(const Line &a, const Line &b) { return sgn(cross(a.t - a.s, b.t - b.s)) != 0 || sgn(cross(a.t - a.s, b.s - a.s)) == 0; }
  bool has_intersected(const Circle &a, const Point &b) { return sgn(distance(a.p, b) - a.r) == 0; }
  bool has_intersected(const Circle &a, const Segment &b) { return sgn(a.r - distance(b, a.p)) != -1 && sgn(max(distance(a.p, b.s), distance(a.p, b.t)) - a.r) != -1; }
  bool has_intersected(const Circle &a, const Line &b) { return sgn(a.r - distance(b, a.p)) != -1; }
  bool has_intersected(const Circle &a, const Circle &b) { return sizeof_common_tangent(a, b) > 0; }

  Point intersection(const Line &a, const Line &b) {
    assert(has_intersected(a, b) && !is_parallel(a, b));
    return a.s + (a.t - a.s) * cross(b.t - b.s, b.s - a.s) / cross(b.t - b.s, a.t - a.s);
  }
  Point intersection(const Segment &a, const Segment &b) {
    assert(has_intersected(a, b));
    if (is_parallel(a, b)) {
      if (sgn(distance(a.s, b.s)) == 0) {
        assert(sgn(dot(a.t - a.s, b.t - a.s)) == -1);
        return a.s;
      } else if (sgn(distance(a.s, b.t)) == 0) {
        assert(sgn(dot(a.t - a.s, b.s - a.s)) == -1);
        return a.s;
      } else if (sgn(distance(a.t, b.s)) == 0) {
        assert(sgn(dot(a.s - a.t, b.t - a.t)) == -1);
        return a.t;
      } else if (sgn(distance(a.t, b.t)) == 0) {
        assert(sgn(dot(a.s - a.t, b.s - a.t)) == -1);
        return a.t;
      } else {
        assert(false);
      }
    } else {
      return intersection(Line(a.s, a.t), Line(b.s, b.t));
    }
  }
  Point intersection(const Line &a, const Segment &b) {
    assert(has_intersected(a, b));
    return intersection(a, Line(b.s, b.t));
  }
  vector<Point> intersection(const Circle &a, const Line &b) {
    Point pro = projection(b, a.p);
    Real nor = (a.p - pro).norm();
    int sign = sgn(a.r - sqrt(nor));
    if (sign == -1) return {};
    if (sign == 0) return {pro};
    Point v = (b.t - b.s).unit_vector() * sqrt(a.r * a.r - nor);
    return {pro + v, pro - v};
  }
  vector<Point> intersection(const Circle &a, const Segment &b) {
    if (!has_intersected(a, b)) return {};
    vector<Point> res = intersection(a, Line(b.s, b.t));
    if (sgn(distance(a.p, b.s) - a.r) != -1 && sgn(distance(a.p, b.t) - a.r) != -1) return res;
    return {sgn(dot(res[0] - b.s, res[0] - b.t)) == 1 ? res[1] : res[0]};
  }
  vector<Point> intersection(const Circle &a, const Circle &b) {
    int sz = sizeof_common_tangent(a, b);
    if (sz == 0 || sz == 4) return {};
    Real alpha = (b.p - a.p).arg();
    if (sz == 1 || sz == 3) return {Point(a.p.x + a.r * cos(alpha), a.p.y + a.r * sin(alpha))};
    Real dist = (b.p - a.p).norm(), beta = acos((dist + a.r * a.r - b.r * b.r) / (2 * sqrt(dist) * a.r));
    return {a.p + Point(a.r * cos(alpha + beta), a.r * sin(alpha + beta)), a.p + Point(a.r * cos(alpha - beta), a.r * sin(alpha - beta))};
  }

  Real distance(const Point &a, const Point &b) { return (b - a).abs(); }
  Real distance(const Segment &a, const Point &b) {
    Point foot = projection(a, b);
    return has_intersected(a, foot) ? distance(foot, b) : min(distance(a.s, b), distance(a.t, b));
  }
  Real distance(const Segment &a, const Segment &b) { return has_intersected(a, b) ? 0 : min({distance(a, b.s), distance(a, b.t), distance(b, a.s), distance(b, a.t)}); }
  Real distance(const Line &a, const Point &b) { return distance(projection(a, b), b); }
  Real distance(const Line &a, const Segment &b) { return has_intersected(a, b) ? 0 : min(distance(a, b.s), distance(a, b.t)); }
  Real distance(const Line &a, const Line &b) { return has_intersected(a, b) ? 0 : distance(a, b.s); }

  vector<Point> tangency(const Circle &a, const Point &b) {
    Real dist = distance(a.p, b);
    int sign = sgn(dist - a.r);
    if (sign == -1) return {};
    if (sign == 0) return {b};
    Real alpha = (b - a.p).arg(), beta = acos(a.r / dist);
    return {a.p + Point(a.r * cos(alpha + beta), a.r * sin(alpha + beta)), a.p + Point(a.r * cos(alpha - beta), a.r * sin(alpha - beta))};
  }
  int sizeof_common_tangent(const Circle &a, const Circle &b) {
    Real dist = distance(a.p, b.p);
    int sign = sgn(a.r + b.r - dist);
    if (sign == -1) return 4;
    if (sign == 0) return 3;
    sign = sgn((sgn(a.r - b.r) == -1 ? b.r - a.r : a.r - b.r) - dist);
    if (sign == -1) return 2;
    if (sign == 0) return 1;
    return 0;
  }
  vector<Line> common_tangent(const Circle &a, const Circle &b) {
    vector<Line> tangents;
    Real dist = distance(a.p, b.p), argument = (b.p - a.p).arg();
    int sign = sgn(a.r + b.r - dist);
    if (sign == -1) {
      Real ac = acos((a.r + b.r) / dist), alpha = argument + ac, cs = cos(alpha), sn = sin(alpha);
      tangents.emplace_back(a.p + Point(a.r * cs, a.r * sn), b.p + Point(-b.r * cs, -b.r * sn));
      alpha = argument - ac; cs = cos(alpha); sn = sin(alpha);
      tangents.emplace_back(a.p + Point(a.r * cs, a.r * sn), b.p + Point(-b.r * cs, -b.r * sn));
    } else if (sign == 0) {
      Point s = a.p + Point(a.r * cos(argument), a.r * sin(argument));
      tangents.emplace_back(s, s + (b.p - a.p).normal_unit_vector().first);
    }
    if (sgn(b.r - a.r) == -1) {
      sign = sgn(a.r - b.r - dist);
      if (sign == -1) {
        Real at = acos((a.r - b.r) / dist), alpha = argument + at, cs = cos(alpha), sn = sin(alpha);
        tangents.emplace_back(a.p + Point(a.r * cs, a.r * sn), b.p + Point(b.r * cs, b.r * sn));
        alpha = argument - at; cs = cos(alpha); sn = sin(alpha);
        tangents.emplace_back(a.p + Point(a.r * cs, a.r * sn), b.p + Point(b.r * cs, b.r * sn));
      } else if (sign == 0) {
        Point s = a.p + Point(a.r * cos(argument), a.r * sin(argument));
        tangents.emplace_back(s, s + (b.p - a.p).normal_unit_vector().first);
      }
    } else {
      sign = sgn(b.r - a.r - dist);
      if (sign == -1) {
        Real at = acos((b.r - a.r) / dist), alpha = argument - at, cs = cos(alpha), sn = sin(alpha);
        tangents.emplace_back(a.p + Point(-a.r * cs, -a.r * sn), b.p + Point(-b.r * cs, -b.r * sn));
        alpha = argument + at; cs = cos(alpha); sn = sin(alpha);
        tangents.emplace_back(a.p + Point(-a.r * cs, -a.r * sn), b.p + Point(-b.r * cs, -b.r * sn));
      } else if (sign == 0) {
        Point s = b.p + Point(-b.r * cos(argument), -b.r * sin(argument));
        tangents.emplace_back(s, s + (a.p - b.p).normal_unit_vector().first);
      }
    }
    return tangents;
  }

  Real intersection_area(const Circle &a, const Circle &b) {
    Real nor = (b.p - a.p).norm(), dist = sqrt(nor);
    if (sgn(a.r + b.r - dist) != 1) return 0;
    if (sgn(abs(a.r - b.r) - dist) != -1) return min(a.r, b.r) * min(a.r, b.r) * M_PI;
    Real alpha = acos((nor + a.r * a.r - b.r * b.r) / (2 * dist * a.r)), beta = acos((nor + b.r * b.r - a.r * a.r) / (2 * dist * b.r));
    return (alpha - sin(alpha + alpha) * 0.5) * a.r * a.r + (beta - sin(beta + beta) * 0.5) * b.r * b.r;
  }

  using Polygon = vector<Point>;

  Real area(const Polygon &a) {
    int n = a.size();
    Real res = 0;
    REP(i, n) res += cross(a[i], a[(i + 1) % n]);
    return res * 0.5;
  }

  Point centroid(const Polygon &a) {
    Point res(0, 0);
    int n = a.size();
    Real den = 0;
    REP(i, n) {
      Real cro = cross(a[i], a[(i + 1) % n]);
      res += (a[i] + a[(i + 1) % n]) / 3 * cro;
      den += cro;
    }
    return res / den;
  }

  int is_contained(const Polygon &a, const Point &b) {
    int n = a.size();
    bool is_in = false;
    REP(i, n) {
      Point p = a[i] - b, q = a[(i + 1) % n] - b;
      if (sgn(q.y - p.y) == -1) swap(p, q);
      int sign = sgn(cross(p, q));
      if (sign == 1 && sgn(p.y) != 1 && sgn(q.y) == 1) is_in = !is_in;
      if (sign == 0 && sgn(dot(p, q)) != 1) return 1;
    }
    return is_in ? 2 : 0;
  }

  bool is_convex(const Polygon &a) {
    int n = a.size();
    REP(i, n) {
      if (ccw(a[(i - 1 + n) % n], a[i], a[(i + 1) % n]) == -1) return false;
    }
    return true;
  }

  Polygon monotone_chain(vector<Point> ps, bool tight = true) {
    sort(ALL(ps));
    int n = ps.size(), idx = 0;
    Polygon convex_hull(n << 1);
    for (int i = 0; i < n; convex_hull[idx++] = ps[i++]) {
      while (idx >= 2 && sgn(cross(convex_hull[idx - 1] - convex_hull[idx - 2], ps[i] - convex_hull[idx - 1])) < tight) --idx;
    }
    for (int i = n - 2, border = idx + 1; i >= 0; convex_hull[idx++] = ps[i--]) {
      while (idx >= border && sgn(cross(convex_hull[idx - 1] - convex_hull[idx - 2], ps[i] - convex_hull[idx - 1])) < tight) --idx;
    }
    convex_hull.resize(idx - 1);
    return convex_hull;
  }

  Polygon cut_convex(const Polygon &a, const Line &b) {
    int n = a.size();
    Polygon res;
    REP(i, n) {
      int c = ccw(b.s, b.t, a[i]);
      if (c != -1) res.emplace_back(a[i]);
      if (c * ccw(b.s, b.t, a[(i + 1) % n]) == -1) res.emplace_back(intersection(Line(a[i], a[(i + 1) % n]), b));
    }
    if (res.size() < 3) res.clear();
    return res;
  }

  pair<Point, Point> rotating_calipers(const Polygon &a) {
    int n = a.size(), high = 0, low = 0;
    if (n <= 2) {
      assert(n == 2);
      return {a[0], a[1]};
    }
    FOR(i, 1, n) {
      if (a[i].y > a[high].y) high = i;
      if (a[i].y < a[low].y) low = i;
    }
    Real max_norm = (a[high] - a[low]).norm();
    int i = high, j = low, max_i = i, max_j = j;
    do {
      ((sgn(cross(a[(i + 1) % n] - a[i], a[(j + 1) % n] - a[j])) != -1 ? j : i) += 1) %= n;
      Real tmp = (a[j] - a[i]).norm();
      if (sgn(tmp - max_norm) == 1) {
        max_norm = tmp;
        max_i = i; max_j = j;
      }
    } while (i != high || j != low);
    return {a[max_i], a[max_j]};
  }
}

vector<double> quadratic_equation(double a, double b, double c) {
  if (abs(a) < EPS) {
    if (abs(b) < EPS) {
      assert(abs(c) >= EPS);
      return {};
    }
    return {-c / b};
  }
  double d = b * b - 4 * a * c;
  if (abs(d) < EPS) return {-0.5 * b / a};
  if (d <= -EPS) return {};
  d = sqrt(d);
  double x1 = -0.5 * (b >= 0 ? b + d : b - d) / a, x2 = c / (x1 * a);
  if (x1 > x2) swap(x1, x2);
  return {x1, x2};
}

using namespace Geometry;

int main() {
  while (true) {
    int n, m; cin >> n >> m;
    if (n == 0 && m == 0) break;
    vector<pair<Point, double>> dog;
    REP(_, n) {
      Point d; double v; cin >> d >> v;
      dog.emplace_back(d, v);
    }
    vector<int> ans(n, 0);
    while (m--) {
      Point fp, fv; cin >> fp >> fv;
      vector<double> t(n, INF);
      REP(i, n) {
        Point d; double v; tie(d, v) = dog[i];
        vector<double> ans = quadratic_equation(fv.norm() - v * v, dot(fp - d, fv) * 2, (fp - d).norm());
        while (!ans.empty()) {
          if (ans.back() >= 0) t[i] = ans.back();
          ans.pop_back();
        }
      }
      double frisbee = *min_element(ALL(t));
      // cout << frisbee << '\n';
      REP(i, n) {
        if (abs(t[i] - INF) < EPS) continue;
        if (abs(frisbee - t[i]) < EPS) ++ans[i];
        Point cat = fp + fv * t[i];
        dog[i].first += (cat - dog[i].first) * frisbee / t[i];
      }
      // REP(i, n) cout << dog[i].first << " \n"[i + 1 == n];
    }
    REP(i, n) cout << ans[i] << " \n"[i + 1 == n];
  }
  return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 3216
final_rank: 8

code_snippet: #include <bits/stdc++.h>
#ifdef LOCAL
#include "../cxx-prettyprint/prettyprint.hpp"
#endif
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> P;

#define REP(i, n) for (int (i) = 0 ; (i) < (int)(n) ; ++(i))
#define REPN(i, m, n) for (int (i) = m ; (i) < (int)(n) ; ++(i))
#define REP_REV(i, n) for (int (i) = (int)(n) - 1 ; (i) >= 0 ; --(i))
#define REPN_REV(i, m, n) for (int (i) = (int)(n) - 1 ; (i) >= m ; --(i))
#define ALL(x) x.begin(), x.end()

#define INF ((1 << 29)-1)
#define MOD (1000000007)

#define print2D(h, w, arr) REP(i, h) { REP(j, w) cout << arr[i][j] << " "; cout << endl; }
template<class T> void print(const T& x){cout << x << endl;}
template<class T, class... A> void print(const T& first, const A&... rest) { cout << first << " "; print(rest...); }
struct PreMain {PreMain(){cin.tie(0);ios::sync_with_stdio(false);cout<<fixed<<setprecision(20);}} premain;

// ベクトル
namespace Geom {

    const double eps = 1e-9;

    struct Point {
        double x, y;
        explicit Point(double x=0, double y=0): x(x), y(y) {}
        Point& operator+=(const Point& v){ x += v.x; y+= v.y; return *this;}
        Point operator+(const Point& v) const{return Point(*this) += v;}
        Point& operator-=(const Point& v){x -= v.x; y-= v.y; return *this;}
        Point operator-(const Point& v) const{return Point(*this) -= v;}
        Point& operator*=(double s){x *= s; y *= s; return *this;}
        Point operator*(double s) const{return Point(*this) *= s;}
        Point& operator/=(double s){x /= s; y /= s; return *this;}
        Point operator/(double s) const{return Point(*this) /= s;}
        double dot(const Point& v) const {return x*v.x + y*v.y;}        /* 内積 */
        double cross(const Point& v) const {return x*v.y - v.x*y;}      /* 外積 */
        double norm2() const {return x*x + y*y;}                        /* ノルムの二乗*/
        double norm() const {return sqrt(norm2());}                     /* ノルム */
        int quadrant() const { if(y > 0) return x>0 ? 1:2; else return x>0 ? 4:3;} /* 象限判定 */
        Point rot(double theta) {return Point(cos(theta) * x - sin(theta) * y, sin(theta) * x + cos(theta) * y);} // 回転
        Point rot90() {return Point(-y, x);} // 90度回転
    };

    ostream& operator<<(ostream& os, const Point& v) {os<<"("<<v.x<<","<<v.y<<")"; return os;}
    istream& operator>>(istream& is, Point& v){ is >> v.x >> v.y; return is;}

    // 点a, b, cからなる三角形の面積
    double calc_triangle_area(Point a, Point b, Point c) {
        Point v1 = b - a;
        Point v2 = c - a;
        return abs(v1.cross(v2)) / 2;
    }

    // 点a, bを通る直線と点cとの距離
    double calc_distance_between_point_and_line(Point a, Point b, Point c) {
        return abs((b-a).cross(c-a)) / (b-a).norm();
    }

    // 点a, bを端点とする線分と点cとの距離
    double calc_distance_between_point_and_segment(Point a, Point b, Point c) {
        if ((b-a).dot(c-a) < eps) return (c-a).norm();
        if ((a-b).dot(c-b) < eps) return (c-b).norm();
        return calc_distance_between_point_and_line(a, b, c);
    }

    // 点a, bを端点とする線分と点cと点dを端点とする線分の距離
    double calc_distance_between_segments(Point a, Point b, Point c, Point d) {
        double d0 = calc_distance_between_point_and_segment(a, b, c);
        double d1 = calc_distance_between_point_and_segment(a, b, d);
        double d2 = calc_distance_between_point_and_segment(c, d, a);
        double d3 = calc_distance_between_point_and_segment(c, d, b);
        return min(min(d0, d1), min(d2, d3));
    }

    enum RELATION_BETWEEN_SEGMENT_AND_POINT {
        COUNTER_CLOCKWISE = 1,     // p1とp2のp0を挟んだ位置関係が反時計回り
        CLOCKWISE = -1,            // 時計回り
        ONLINE_BACK = 2,           // p1とp2がp0を挟んで直線状にある
        ONLINE_FRONT = -2,         // p0とp2の間にp1がある
        ON_SEGMENT = 0,            // p0とp1の間にp2がある
    };

    // 点cが点a, bを端点とする線分のどちら側にあるか、enumで返す
    RELATION_BETWEEN_SEGMENT_AND_POINT ccw_ex(Point p0, Point p1, Point p2) {
        Point v1 = p1 - p0;
        Point v2 = p2 - p0;
        if(v1.cross(v2) > eps) return COUNTER_CLOCKWISE;    // 1
        if(v1.cross(v2) < -eps) return CLOCKWISE;           // -1
        if(v1.dot(v2) < -eps) return ONLINE_BACK;           // 2
        if(v1.norm() < v2.norm()) return ONLINE_FRONT;      // -2
        return ON_SEGMENT;                                  // 0
    }

    // 点cが点a, bを端点とする線分のどちら側にあるか
    int ccw(Point p0, Point p1, Point p2) {
        Point v1 = p1 - p0;
        Point v2 = p2 - p0;
        if(v1.cross(v2) > eps) return 1;
        if(v1.cross(v2) < -eps) return -1;
        return 0;
    }

    // p1,p2を端点とする線分Aとp3,p4を端点とする線分Bの交差判定
    // include_end=trueなら端点が重なっていても交差しているとみなす
    bool intersect(Point p1, Point p2, Point p3, Point p4, bool include_end=true) {

        bool is_otherside;
        bool is_inside;

        if (include_end){
            is_otherside = ccw(p1,p2,p3) * ccw(p1,p2,p4) <= 0; // Aの両側にBの端点があるかどうか。どちらかがAの直線状にいてもOK
            is_inside = ccw(p3,p4,p1) * ccw(p3,p4,p2) <= 0;    // Aの端点の内側にBがいるかどうか。
        } else {
            is_otherside = ccw(p1,p2,p3) * ccw(p1,p2,p4) < 0; // Aの両側にBの端点があるかどうか
            is_inside = ccw(p3,p4,p1) * ccw(p3,p4,p2) < 0;    // Aの端点の内側にBがいるかどうか
        }
        return is_otherside && is_inside;
    }


    // 円
    struct Circle {
        Point c;
        double r;
        Circle(){}
        Circle(Point c, double r):c(c),r(r){}

        // 円が点pを含むかどうか　include_circumは円周上を含むとするかどうか
        bool does_include_point(Point p, bool include_circum = true){
            double d = (p - c).norm();
            if (include_circum){
                return d < r + eps;
            } else {
                return d < r - eps;
            }
        }
    };

    // 点p1, p2を通る半径rの円を返す
    vector<Circle> calc_circle_on_two_points(Point p1, Point p2, double r){

        Point p12_half = (p2 - p1) / 2.0;

        double n_vec_norm2 = r*r - p12_half.norm2();
        if (n_vec_norm2 < 0) return vector<Circle>();

        double n_vec_norm = sqrt(n_vec_norm2);
        Point n_vec = p12_half.rot90() * n_vec_norm / p12_half.norm();

        vector<Circle> ret;
        ret.emplace_back(p1 + p12_half + n_vec, 1.0);
        ret.emplace_back(p1 + p12_half - n_vec, 1.0);
        return ret;
    }
}


int main(){
#ifdef LOCAL
    ifstream in("../in.txt"); cin.rdbuf(in.rdbuf());
#endif
    using namespace Geom;

    while(1){
        int n, m;
        cin >> n >> m;
        if(n == 0 && m == 0){
            break;
        }

        vector<int> ans(n, 0);
        double time;

        vector<Point> d_pos(n);
        vector<Point> d_dst(n);
        vector<double> d_speed(n);

        vector<Point> f_pos(m);
        vector<Point> f_dst(m);
                
        REP(i, n) cin >> d_pos[i] >> d_speed[i];
        REP(i, m) cin >> f_pos[i] >> f_dst[i];

        for(int i=0; i<m; i++){
            double min_t = INF;
            int min_dog = n;

            time = INF;

            /* 最小の時間を求める */
            for(int j=0; j<n; j++){
                double ds = d_speed[j];
                Point dd = f_pos[i] - d_pos[j];
                double a = f_dst[i].norm2() - ds*ds;
                double b = 2 * dd.dot(f_dst[i]);
                double c = dd.norm2();
                if(abs(a) < eps){
                    time = -c/b;
                    if(time < 0) time = INF;
                    //print("asdf");
                } else {
                    double D = b*b - 4*a*c;
                    if(D < 0) {
                        time = INF;
                    }else{
                        double ans_t1 = (-b + sqrt(D)) / (2*a);
                        double ans_t2 = (-b - sqrt(D)) / (2*a);
                        if(ans_t1 < 0) ans_t1 = INF;
                        if(ans_t2 < 0) ans_t2 = INF;
                        time = min(ans_t1, ans_t2);                    
                    }
                }


                if(time < min_t){
                    min_t = time;
                    min_dog = j;
                }

                d_dst[j] = (f_pos[i] + f_dst[i] * time - d_pos[j]) / time; 
                if(time == INF) d_dst[j] = Point(0, 0);
            }

            /* 犬の座標を更新する */
            for(int j=0; j<n; j++){
                d_pos[j] += d_dst[j] * min_t;
            }

            ans[min_dog]++;
        }

        for(int i=0; i<n-1; i++){
            cout << ans[i] <<" ";
        }
        print(ans[n-1]);
    }

    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 3224
final_rank: 7

code_snippet: #pragma GCC optimize ("O3")

using namespace std;

#include <bits/stdc++.h>

using QWORD  = uint64_t;
using SQWORD = int64_t;
using DWORD  = uint32_t;
using SDWORD = int32_t;
using WORD   = uint16_t;
using SWORD  = int16_t;
using BYTE   = uint8_t;
using SBYTE  = int8_t;
using DOUBLE = double;
using FLOAT  = float;

#define MIN_SDWORD (-2147483648)
#define MAX_SDWORD (2147483647)
#define MIN_SBYTE (-128)
#define MAX_SBYTE (127)

#define MIN_SQWORD (0x8000000000000000)
#define MAX_SQWORD (0x7FFFFFFFFFFFFFFF)

#define MAX_QWORD  (0xFFFFFFFFFFFFFFFF)
#define MAX_DWORD  (0xFFFFFFFF)
#define MAX_WORD   (0xFFFF)
#define MAX_BYTE   (0xFF)

#define MAX_DOUBLE      (1.0e+100)
#define DOUBLE_EPS      (1.0e-12)
#define MIN_DOUBLE_N    (-1.0e+100)

#define ArrayLength(a)  (sizeof(a) / sizeof(a[0]))

static inline DOUBLE MAX(DOUBLE a, DOUBLE b) { return a > b ? a : b; }
static inline QWORD MAX(QWORD a, QWORD b) { return a > b ? a : b; }
static inline DWORD MAX(DWORD a, DWORD b) { return a > b ? a : b; }
static inline SDWORD MAX(SDWORD a, SDWORD b) { return a > b ? a : b; }
static inline DOUBLE MIN(DOUBLE a, DOUBLE b) { return a < b ? a : b; }
static inline QWORD MIN(QWORD a, QWORD b) { return a < b ? a : b; }
static inline DWORD MIN(DWORD a, DWORD b) { return a < b ? a : b; }
static inline SDWORD MIN(SDWORD a, SDWORD b) { return a < b ? a : b; }

static inline DOUBLE ABS(DOUBLE a) { return 0.0 < (a) ? (a) : -(a); };

#define BYTE_BITS   (8)
#define WORD_BITS   (16)
#define DWORD_BITS  (32)
#define QWORD_BITS  (64)

static const DOUBLE d_PI = 3.14159265357989;

static inline void inputStringSpSeparated(char *pcStr)
{
    char *pcCur = pcStr;
    for (;;) {
        char c = getchar();
        if (('\n' == c) || (EOF == c) || (' ' == c)) {
            break;
        }
        *pcCur = c;
        pcCur++;
    }
    *pcCur = '\0';
}

static inline void inputString(char *pcStr)
{
    char *pcCur = pcStr;
    for (;;) {
        char c = getchar();
        if (('\n' == c) || (EOF == c)) {
            break;
        }
        *pcCur = c;
        pcCur++;
    }
    *pcCur = '\0';
}


static inline SQWORD inputSQWORD(void)
{
    SQWORD sqNumber = 0;
    SQWORD sqMultiplier = 1;
    bool bRead = false;
    for (;;) {
        char c = getchar();
        if (!bRead) {
            if ('-' == c) {
                sqMultiplier = -1;
            }
        }
        if (('0' <= c) && (c <= '9')) {
            sqNumber *= 10LL;
            sqNumber += (SQWORD)(c - '0');
            bRead = true;
        } else {
            if (bRead) {
                return sqNumber * sqMultiplier;
            }
        }
    }
}


static inline SDWORD inputSDWORD(void)
{
    SDWORD lNumber = 0;
    SDWORD lMultiplier = 1;
    bool bRead = false;
    for (;;) {
        char c = getchar();
        if (!bRead) {
            if ('-' == c) {
                lMultiplier = -1;
            }
        }
        if (('0' <= c) && (c <= '9')) {
            lNumber *= 10;
            lNumber += (c - '0');
            bRead = true;
        } else {
            if (bRead) {
                return lNumber * lMultiplier;
            }
        }
    }
}

static inline DOUBLE inputFP(void)
{
    DOUBLE dInt = 0.0;
    DOUBLE dFrac = 0.0;
    DOUBLE dMultiplier = 1.0;
    DWORD dwFpCnt = 0;
    DOUBLE *pdCur = &dInt;
    bool bRead = false;
    for (;;) {
        char c = getchar();
        if (!bRead) {
            if ('-' == c) {
                dMultiplier = -1;
            }
        }
        if ('.' == c) {
            pdCur = &dFrac;
        } else if (('0' <= c) && (c <= '9')) {
            (*pdCur) *= 10;
            (*pdCur) += (DOUBLE)(c - '0');
            bRead = true;
            if (pdCur == &dFrac) {
                dwFpCnt++;
            }
        } else {
            if (bRead) {
                return dMultiplier * (dInt + dFrac / (pow((DOUBLE)10.0 , (DOUBLE)dwFpCnt)));
            }
        }
    }
}

/*----------------------------------------------*/
/**
 *  mod による操作ライブラリ
 */
#define ANS_MOD (1000000007)

class MODINT {
    static SQWORD MOD;
    SQWORD m_x;

public:
    MODINT(SQWORD val) {
        m_x = (val % MOD + MOD) % MOD;
    };
    MODINT() {
        m_x = 0;
    }
    static void Init(SQWORD sqMod) {
        MOD = sqMod;
    }

	MODINT& operator+= (const MODINT a)
    {
        m_x = (m_x + a.m_x) % MOD; 
        return *this;
    };
	MODINT& operator-= (const MODINT a)
    { 
        m_x = (m_x - a.m_x + MOD) % MOD; 
        return *this;
    };
	MODINT& operator*= (const MODINT a)
    {
        m_x = (m_x * a.m_x) % MOD;
        return *this;
    };
    MODINT pow(SQWORD t) const {
        if (!t) return 1;
        MODINT a = pow(t>>1);
        a *= a;
        if (t&1) a *= *this;
        return a;
    }
	MODINT operator+ (const MODINT a) const {
		MODINT res(*this);
		return (res += a);
	}
	MODINT operator- (const MODINT a) const {
		MODINT res(*this);
		return (res -= a);
	}
	MODINT operator* (const MODINT a) const {
		MODINT res(*this);
		return (res *= a);
	}
	MODINT operator/ (const MODINT a) const {
		MODINT res(*this);
		return (res /= a);
	}

    /* 逆元 */
    MODINT inv() const {
        return pow(MOD-2);
    }

    /* 除算 */
    MODINT& operator/=(const MODINT a) {
        return (*this) *= a.inv();
    } 

    /* 整数版 */
	MODINT& operator+= (const SQWORD a) {*this += MODINT(a); return *this;};
	MODINT& operator-= (const SQWORD a) {*this -= MODINT(a); return *this;};
	MODINT& operator*= (const SQWORD a) {*this *= MODINT(a); return *this;};
	MODINT& operator/= (const SQWORD a) {*this /= MODINT(a); return *this;};

    SQWORD getVal() { return m_x; };
};
SQWORD MODINT::MOD = ANS_MOD;


/*----------------------------------------------*/


struct VECTOR_2D {
    DOUBLE dX;
    DOUBLE dY;
    VECTOR_2D(DOUBLE x, DOUBLE y) : dX(x), dY(y) {};
    VECTOR_2D() : dX(0), dY(0) {};

    /* 加算 */
	VECTOR_2D& operator+= (const VECTOR_2D a)
    { 
        dX = dX + a.dX;
        dY = dY + a.dY;
        return *this;
    };
    const VECTOR_2D operator+ (const VECTOR_2D a) const {
		return VECTOR_2D(dX + a.dX, dY + a.dY); 
    };

    /* 減算 */
	VECTOR_2D& operator-= (const VECTOR_2D a)
    { 
        dX = dX - a.dX;
        dY = dY - a.dY;
        return *this;
    };
    const VECTOR_2D operator- (const VECTOR_2D a) const {
		return VECTOR_2D(dX - a.dX, dY - a.dY);
    };

    /* 定数倍 */
	VECTOR_2D& operator*= (const DOUBLE a)
    { 
        dX = dX * a;
        dY = dY * a;
        return *this;
    };
    const VECTOR_2D operator* (const DOUBLE a) const {
		return VECTOR_2D(dX * a, dY * a); 
    };

    DOUBLE norm(void) const {
        return (dX * dX + dY * dY);
    }

    DOUBLE dist(void) const {
        return sqrt(norm());
    }

    DOUBLE angle(void) const {
        return atan2(dY, dX);
    }
};

/*----------------------------------------------*/

struct FRESBEE_ST {
    VECTOR_2D stStrtPos;
    VECTOR_2D stVel;

    FRESBEE_ST(const VECTOR_2D &p, const VECTOR_2D &v) : stStrtPos(p), stVel(v) {};
};


static bool solve2DEquation(
    DOUBLE dA, DOUBLE dB, DOUBLE dC, DOUBLE &dAns1, DOUBLE &dAns2)
{
    if (abs(dA) < DOUBLE_EPS) {
        /* 1d equation */
        if (abs(dB) < DOUBLE_EPS) {
            return false;
        } else {
            dAns1 = - dC / dB;
            dAns2 = dAns1;
            return true;
        }
    }

    DOUBLE dSq = dB * dB - 4.0 * dA * dC;

    if (dSq < 0) {
        return false;
    }
    DOUBLE dAns_a = (-dB + sqrt(dSq)) / (2.0 * dA);
    DOUBLE dAns_b = (-dB - sqrt(dSq)) / (2.0 * dA);
   
    dAns1 = max(dAns_a, dAns_b);
    dAns2 = min(dAns_a, dAns_b);
    return true;
}


static DOUBLE getCatchTime(
    DOUBLE dTheta, 
    DOUBLE dDist,
    DOUBLE dVelFres,
    DOUBLE dVelDog,
    DOUBLE &dTime)
{
    DOUBLE dA = (dVelFres * dVelFres - dVelDog * dVelDog);
    DOUBLE dB = -2.0 * dDist * cos(dTheta) * dVelFres;
    DOUBLE dC = dDist * dDist;

    DOUBLE dAns1, dAns2;

    if (!solve2DEquation(dA, dB, dC, dAns1, dAns2)) {
//        printf("2d equation false1\n");
        return false;
    }

    if (dAns2 < 0) {
        if (dAns1 < 0) {
//            printf("2d equation false2\n");
            dTime = MAX_DOUBLE;
            return false;
        } else {
            dTime = dAns1;
        }
    } else {
        dTime = dAns2;
    }

//    printf("2d equation -> time %f\n", dTime);
    return true;
}


static bool getCatchTimeOneDog(
    SQWORD sqDogIdx,
    DOUBLE dVelDog,
    const vector<VECTOR_2D> &vecstDogPos,
    const FRESBEE_ST &stFresbee,
    DOUBLE &dCatchTime)
{
    VECTOR_2D stDogPos = vecstDogPos[sqDogIdx];
    VECTOR_2D stFtoD;
    stFtoD = stDogPos - stFresbee.stStrtPos;
    DOUBLE dAngleDog     = atan2(stFtoD.dY, stFtoD.dX);
    DOUBLE dAngleFresbee = atan2(stFresbee.stVel.dY, stFresbee.stVel.dX);
    DOUBLE dTheta = min(abs(dAngleDog - dAngleFresbee), (2.0 * d_PI - abs(dAngleDog - dAngleFresbee)));

    DOUBLE dDist = stFtoD.dist();
    DOUBLE dVelFres = sqrt(stFresbee.stVel.norm());
//    printf("theta = %lf dist = %lf, dVel = %lf\n", dTheta, dDist, dVelFres);
    DOUBLE dTime = MAX_DOUBLE;

    bool bCatchable = getCatchTime(dTheta, dDist, dVelFres, dVelDog, dTime);
    dCatchTime = dTime;

    return bCatchable;
}

static bool solve()
{
    SQWORD sqN = inputSQWORD();
    SQWORD sqM = inputSQWORD();

//    printf("solve ---> %d %d\n", sqN, sqM);

    if ((0 == sqN) && (0 == sqM)) {
        return false;
    }

    vector<VECTOR_2D> vecPosDogs;
    vector<DOUBLE> vecdVelDogs;
    vector<FRESBEE_ST> vecstFresbee;

    for (SQWORD sqIdx = 0; sqIdx < sqN; sqIdx++) {
        DOUBLE dX = inputFP();
        DOUBLE dY = inputFP();
        DOUBLE dV = inputFP();
        vecPosDogs.emplace_back(dX, dY);
        vecdVelDogs.emplace_back(dV);
    }
    for (SQWORD sqIdx = 0; sqIdx < sqM; sqIdx++) {
        DOUBLE dFx = inputFP();
        DOUBLE dFy = inputFP();
        DOUBLE dFvx = inputFP();
        DOUBLE dFvy = inputFP();
        vecstFresbee.emplace_back(VECTOR_2D(dFx, dFy), VECTOR_2D(dFvx, dFvy));
    }

    vector<SQWORD> vecCatchCnt(sqN, 0);
    for (SQWORD sqIter = 0; sqIter < sqM; sqIter++) {
        vector<DOUBLE> vecdCatchTime(sqN, MAX_DOUBLE);
        for (SQWORD sqDogIdx = 0; sqDogIdx < sqN; sqDogIdx++) {
            bool bCatchable = getCatchTimeOneDog(sqDogIdx, vecdVelDogs[sqDogIdx], vecPosDogs, 
                                                    vecstFresbee[sqIter], vecdCatchTime[sqDogIdx]);
#if 0
            if (bCatchable) {
                printf(">>> %llf\n", vecdCatchTime[sqDogIdx]);
            } else {
                printf(">>> NG\n");
            }
#endif
        }

        auto min_iter = min_element(vecdCatchTime.begin(), vecdCatchTime.end());
        vecCatchCnt[min_iter - vecdCatchTime.begin()] ++;

        DOUBLE dMinCatchTime = *min_iter;
//        printf("time [%llf]\n", dMinCatchTime);

        /* 犬の位置を更新する */
        for (SQWORD sqDogIdx = 0; sqDogIdx < sqN; sqDogIdx++) {
            DOUBLE dCatchTime = vecdCatchTime[sqDogIdx];
            if (dCatchTime != MAX_DOUBLE) {
                VECTOR_2D stInitPos   = vecPosDogs[sqDogIdx];
                VECTOR_2D stTargetPos = vecstFresbee[sqIter].stStrtPos + vecstFresbee[sqIter].stVel * dCatchTime;
                VECTOR_2D stNextPos   = stInitPos + ((stTargetPos - stInitPos) * (dMinCatchTime / dCatchTime));
//                printf("catch [%llf %llf] tgt[%llf %llf]\n", dCatchTime, dMinCatchTime, stTargetPos.dX, stTargetPos.dY);

                vecPosDogs[sqDogIdx] = stNextPos;
            }
//            printf("iter[%d] dog[%d] %llf %llf\n", sqIter, sqDogIdx, vecPosDogs[sqDogIdx].dX, vecPosDogs[sqDogIdx].dY);
        }
    }
    for (SDWORD lIdx = 0; lIdx < sqN; lIdx++) {
        printf("%lld", vecCatchCnt[lIdx]);
        if (lIdx != sqN - 1) {
            printf(" ");
        } else {
            printf("\n");
        }
    }

    return true;
}

int main(void)
{
    while(1) {
        if (!solve()) {
            break;
        }
    }
}
accuracy: 1
time_ms: 80
memory_kb: 3624
final_rank: 14

code_snippet: #pragma GCC optimize ("O3")

using namespace std;

#include <bits/stdc++.h>

using QWORD  = uint64_t;
using SQWORD = int64_t;
using DWORD  = uint32_t;
using SDWORD = int32_t;
using WORD   = uint16_t;
using SWORD  = int16_t;
using BYTE   = uint8_t;
using SBYTE  = int8_t;
using DOUBLE = double;
using FLOAT  = float;

#define MIN_SDWORD (-2147483648)
#define MAX_SDWORD (2147483647)
#define MIN_SBYTE (-128)
#define MAX_SBYTE (127)

#define MIN_SQWORD (0x8000000000000000)
#define MAX_SQWORD (0x7FFFFFFFFFFFFFFF)

#define MAX_QWORD  (0xFFFFFFFFFFFFFFFF)
#define MAX_DWORD  (0xFFFFFFFF)
#define MAX_WORD   (0xFFFF)
#define MAX_BYTE   (0xFF)

#define MAX_DOUBLE      (1.0e+100)
#define DOUBLE_EPS      (1.0e-12)
#define MIN_DOUBLE_N    (-1.0e+100)

#define ArrayLength(a)  (sizeof(a) / sizeof(a[0]))

static inline DOUBLE MAX(DOUBLE a, DOUBLE b) { return a > b ? a : b; }
static inline QWORD MAX(QWORD a, QWORD b) { return a > b ? a : b; }
static inline DWORD MAX(DWORD a, DWORD b) { return a > b ? a : b; }
static inline SDWORD MAX(SDWORD a, SDWORD b) { return a > b ? a : b; }
static inline DOUBLE MIN(DOUBLE a, DOUBLE b) { return a < b ? a : b; }
static inline QWORD MIN(QWORD a, QWORD b) { return a < b ? a : b; }
static inline DWORD MIN(DWORD a, DWORD b) { return a < b ? a : b; }
static inline SDWORD MIN(SDWORD a, SDWORD b) { return a < b ? a : b; }

static inline DOUBLE ABS(DOUBLE a) { return 0.0 < (a) ? (a) : -(a); };

#define BYTE_BITS   (8)
#define WORD_BITS   (16)
#define DWORD_BITS  (32)
#define QWORD_BITS  (64)

static const DOUBLE d_PI = 3.14159265357989;

static inline void inputStringSpSeparated(char *pcStr)
{
    char *pcCur = pcStr;
    for (;;) {
        char c = getchar();
        if (('\n' == c) || (EOF == c) || (' ' == c)) {
            break;
        }
        *pcCur = c;
        pcCur++;
    }
    *pcCur = '\0';
}

static inline void inputString(char *pcStr)
{
    char *pcCur = pcStr;
    for (;;) {
        char c = getchar();
        if (('\n' == c) || (EOF == c)) {
            break;
        }
        *pcCur = c;
        pcCur++;
    }
    *pcCur = '\0';
}


static inline SQWORD inputSQWORD(void)
{
    SQWORD sqNumber = 0;
    SQWORD sqMultiplier = 1;
    bool bRead = false;
    for (;;) {
        char c = getchar();
        if (!bRead) {
            if ('-' == c) {
                sqMultiplier = -1;
            }
        }
        if (('0' <= c) && (c <= '9')) {
            sqNumber *= 10LL;
            sqNumber += (SQWORD)(c - '0');
            bRead = true;
        } else {
            if (bRead) {
                return sqNumber * sqMultiplier;
            }
        }
    }
}


static inline SDWORD inputSDWORD(void)
{
    SDWORD lNumber = 0;
    SDWORD lMultiplier = 1;
    bool bRead = false;
    for (;;) {
        char c = getchar();
        if (!bRead) {
            if ('-' == c) {
                lMultiplier = -1;
            }
        }
        if (('0' <= c) && (c <= '9')) {
            lNumber *= 10;
            lNumber += (c - '0');
            bRead = true;
        } else {
            if (bRead) {
                return lNumber * lMultiplier;
            }
        }
    }
}

static inline DOUBLE inputFP(void)
{
    DOUBLE dInt = 0.0;
    DOUBLE dFrac = 0.0;
    DOUBLE dMultiplier = 1.0;
    DWORD dwFpCnt = 0;
    DOUBLE *pdCur = &dInt;
    bool bRead = false;
    for (;;) {
        char c = getchar();
        if (!bRead) {
            if ('-' == c) {
                dMultiplier = -1;
            }
        }
        if ('.' == c) {
            pdCur = &dFrac;
        } else if (('0' <= c) && (c <= '9')) {
            (*pdCur) *= 10;
            (*pdCur) += (DOUBLE)(c - '0');
            bRead = true;
            if (pdCur == &dFrac) {
                dwFpCnt++;
            }
        } else {
            if (bRead) {
                return dMultiplier * (dInt + dFrac / (pow((DOUBLE)10.0 , (DOUBLE)dwFpCnt)));
            }
        }
    }
}

/*----------------------------------------------*/
/**
 *  mod による操作ライブラリ
 */
#define ANS_MOD (1000000007)

class MODINT {
    static SQWORD MOD;
    SQWORD m_x;

public:
    MODINT(SQWORD val) {
        m_x = (val % MOD + MOD) % MOD;
    };
    MODINT() {
        m_x = 0;
    }
    static void Init(SQWORD sqMod) {
        MOD = sqMod;
    }

	MODINT& operator+= (const MODINT a)
    {
        m_x = (m_x + a.m_x) % MOD; 
        return *this;
    };
	MODINT& operator-= (const MODINT a)
    { 
        m_x = (m_x - a.m_x + MOD) % MOD; 
        return *this;
    };
	MODINT& operator*= (const MODINT a)
    {
        m_x = (m_x * a.m_x) % MOD;
        return *this;
    };
    MODINT pow(SQWORD t) const {
        if (!t) return 1;
        MODINT a = pow(t>>1);
        a *= a;
        if (t&1) a *= *this;
        return a;
    }
	MODINT operator+ (const MODINT a) const {
		MODINT res(*this);
		return (res += a);
	}
	MODINT operator- (const MODINT a) const {
		MODINT res(*this);
		return (res -= a);
	}
	MODINT operator* (const MODINT a) const {
		MODINT res(*this);
		return (res *= a);
	}
	MODINT operator/ (const MODINT a) const {
		MODINT res(*this);
		return (res /= a);
	}

    /* 逆元 */
    MODINT inv() const {
        return pow(MOD-2);
    }

    /* 除算 */
    MODINT& operator/=(const MODINT a) {
        return (*this) *= a.inv();
    } 

    /* 整数版 */
	MODINT& operator+= (const SQWORD a) {*this += MODINT(a); return *this;};
	MODINT& operator-= (const SQWORD a) {*this -= MODINT(a); return *this;};
	MODINT& operator*= (const SQWORD a) {*this *= MODINT(a); return *this;};
	MODINT& operator/= (const SQWORD a) {*this /= MODINT(a); return *this;};

    SQWORD getVal() { return m_x; };
};
SQWORD MODINT::MOD = ANS_MOD;


/*----------------------------------------------*/


struct VECTOR_2D {
    DOUBLE dX;
    DOUBLE dY;
    VECTOR_2D(DOUBLE x, DOUBLE y) : dX(x), dY(y) {};
    VECTOR_2D() : dX(0), dY(0) {};

    /* 加算 */
	VECTOR_2D& operator+= (const VECTOR_2D a)
    { 
        dX = dX + a.dX;
        dY = dY + a.dY;
        return *this;
    };
    const VECTOR_2D operator+ (const VECTOR_2D a) const {
		return VECTOR_2D(dX + a.dX, dY + a.dY); 
    };

    /* 減算 */
	VECTOR_2D& operator-= (const VECTOR_2D a)
    { 
        dX = dX - a.dX;
        dY = dY - a.dY;
        return *this;
    };
    const VECTOR_2D operator- (const VECTOR_2D a) const {
		return VECTOR_2D(dX - a.dX, dY - a.dY);
    };

    /* 定数倍 */
	VECTOR_2D& operator*= (const DOUBLE a)
    { 
        dX = dX * a;
        dY = dY * a;
        return *this;
    };
    const VECTOR_2D operator* (const DOUBLE a) const {
		return VECTOR_2D(dX * a, dY * a); 
    };

    DOUBLE norm(void) const {
        return (dX * dX + dY * dY);
    }

    DOUBLE dist(void) const {
        return sqrt(norm());
    }

    DOUBLE angle(void) const {
        return atan2(dY, dX);
    }
};

/*----------------------------------------------*/

struct FRESBEE_ST {
    VECTOR_2D stStrtPos;
    VECTOR_2D stVel;

    FRESBEE_ST(const VECTOR_2D &p, const VECTOR_2D &v) : stStrtPos(p), stVel(v) {};
};


static bool solve2DEquation(
    DOUBLE dA, DOUBLE dB, DOUBLE dC, DOUBLE &dAns1, DOUBLE &dAns2)
{
    if (abs(dA) < DOUBLE_EPS) {
        /* 1d equation */
        if (abs(dB) < DOUBLE_EPS) {
            return false;
        } else {
            dAns1 = - dC / dB;
            dAns2 = dAns1;
            return true;
        }
    }

    DOUBLE dSq = dB * dB - 4.0 * dA * dC;

    if (dSq < 0) {
        return false;
    }
    DOUBLE dAns_a = (-dB + sqrt(dSq)) / (2.0 * dA);
    DOUBLE dAns_b = (-dB - sqrt(dSq)) / (2.0 * dA);
   
    dAns1 = max(dAns_a, dAns_b);
    dAns2 = min(dAns_a, dAns_b);
    return true;
}


static DOUBLE getCatchTime(
    DOUBLE dTheta, 
    DOUBLE dDist,
    DOUBLE dVelFres,
    DOUBLE dVelDog,
    DOUBLE &dTime)
{
    DOUBLE dA = (dVelFres * dVelFres - dVelDog * dVelDog);
    DOUBLE dB = -2.0 * dDist * cos(dTheta) * dVelFres;
    DOUBLE dC = dDist * dDist;

    DOUBLE dAns1, dAns2;

    if (!solve2DEquation(dA, dB, dC, dAns1, dAns2)) {
//        printf("2d equation false1\n");
        return false;
    }

    if (dAns2 < 0) {
        if (dAns1 < 0) {
//            printf("2d equation false2\n");
            dTime = MAX_DOUBLE;
            return false;
        } else {
            dTime = dAns1;
        }
    } else {
        dTime = dAns2;
    }

//    printf("2d equation -> time %f\n", dTime);
    return true;
}


static bool getCatchTimeOneDog(
    SQWORD sqDogIdx,
    DOUBLE dVelDog,
    const vector<VECTOR_2D> &vecstDogPos,
    const FRESBEE_ST &stFresbee,
    DOUBLE &dCatchTime)
{
    VECTOR_2D stDogPos = vecstDogPos[sqDogIdx];
    VECTOR_2D stFtoD;
    stFtoD = stDogPos - stFresbee.stStrtPos;
    DOUBLE dAngleDog     = atan2(stFtoD.dY, stFtoD.dX);
    DOUBLE dAngleFresbee = atan2(stFresbee.stVel.dY, stFresbee.stVel.dX);
    DOUBLE dTheta = min(ABS(dAngleDog - dAngleFresbee), (2.0 * d_PI - ABS(dAngleDog - dAngleFresbee)));

    DOUBLE dDist = stFtoD.dist();
    DOUBLE dVelFres = sqrt(stFresbee.stVel.norm());
//    printf("theta = %lf dist = %lf, dVel = %lf\n", dTheta, dDist, dVelFres);
    DOUBLE dTime = MAX_DOUBLE;

    bool bCatchable = getCatchTime(dTheta, dDist, dVelFres, dVelDog, dTime);
    dCatchTime = dTime;

    return bCatchable;
}

static bool solve()
{
    SQWORD sqN = inputSQWORD();
    SQWORD sqM = inputSQWORD();

//    printf("solve ---> %d %d\n", sqN, sqM);

    if ((0 == sqN) && (0 == sqM)) {
        return false;
    }

    vector<VECTOR_2D> vecPosDogs;
    vector<DOUBLE> vecdVelDogs;
    vector<FRESBEE_ST> vecstFresbee;

    for (SQWORD sqIdx = 0; sqIdx < sqN; sqIdx++) {
        DOUBLE dX = inputFP();
        DOUBLE dY = inputFP();
        DOUBLE dV = inputFP();
        vecPosDogs.emplace_back(dX, dY);
        vecdVelDogs.emplace_back(dV);
    }
    for (SQWORD sqIdx = 0; sqIdx < sqM; sqIdx++) {
        DOUBLE dFx = inputFP();
        DOUBLE dFy = inputFP();
        DOUBLE dFvx = inputFP();
        DOUBLE dFvy = inputFP();
        vecstFresbee.emplace_back(VECTOR_2D(dFx, dFy), VECTOR_2D(dFvx, dFvy));
    }

    vector<SQWORD> vecCatchCnt(sqN, 0);
    for (SQWORD sqIter = 0; sqIter < sqM; sqIter++) {
        vector<DOUBLE> vecdCatchTime(sqN, MAX_DOUBLE);
        for (SQWORD sqDogIdx = 0; sqDogIdx < sqN; sqDogIdx++) {
            bool bCatchable = getCatchTimeOneDog(sqDogIdx, vecdVelDogs[sqDogIdx], vecPosDogs, 
                                                    vecstFresbee[sqIter], vecdCatchTime[sqDogIdx]);
#if 0
            if (bCatchable) {
                printf(">>> %llf\n", vecdCatchTime[sqDogIdx]);
            } else {
                printf(">>> NG\n");
            }
#endif
        }

        auto min_iter = min_element(vecdCatchTime.begin(), vecdCatchTime.end());
        vecCatchCnt[min_iter - vecdCatchTime.begin()] ++;

        DOUBLE dMinCatchTime = *min_iter;
//        printf("time [%llf]\n", dMinCatchTime);

        /* 犬の位置を更新する */
        for (SQWORD sqDogIdx = 0; sqDogIdx < sqN; sqDogIdx++) {
            DOUBLE dCatchTime = vecdCatchTime[sqDogIdx];
            if (dCatchTime != MAX_DOUBLE) {
                VECTOR_2D stInitPos   = vecPosDogs[sqDogIdx];
                VECTOR_2D stTargetPos = vecstFresbee[sqIter].stStrtPos + vecstFresbee[sqIter].stVel * dCatchTime;
                VECTOR_2D stNextPos   = stInitPos + ((stTargetPos - stInitPos) * (dMinCatchTime / dCatchTime));
//                printf("catch [%llf %llf] tgt[%llf %llf]\n", dCatchTime, dMinCatchTime, stTargetPos.dX, stTargetPos.dY);

                vecPosDogs[sqDogIdx] = stNextPos;
            }
//            printf("iter[%d] dog[%d] %llf %llf\n", sqIter, sqDogIdx, vecPosDogs[sqDogIdx].dX, vecPosDogs[sqDogIdx].dY);
        }
    }
    for (SDWORD lIdx = 0; lIdx < sqN; lIdx++) {
        printf("%lld", vecCatchCnt[lIdx]);
        if (lIdx != sqN - 1) {
            printf(" ");
        } else {
            printf("\n");
        }
    }

    return true;
}

int main(void)
{
    while(1) {
        if (!solve()) {
            break;
        }
    }
}
accuracy: 1
time_ms: 80
memory_kb: 3704
final_rank: 16

code_snippet: #include <algorithm>
#include <iostream>
#include <vector>
#include <cmath>
#include <numeric>
#include <tuple>
#include <assert.h>

#define sqr(x) std::pow(x, 2.0)
#define INF 1e10
#define REP(i, n) for (int i = 0; i < n; i++)
#define POS_OR_INF(x) (x > 0 ? x : INF)

using namespace std;

struct Point {
	double x;
	double y;
};

inline istream& operator >> (istream& is, Point& p) {
	return is >> p.x >> p.y;
}

typedef Point Vector;

struct Dog {
	Point  position;
	double speed;
};

inline std::pair<double, double> solve(const Dog& dog, const Point& fp, const Vector& fv) {
	Vector d = { fp.x - dog.position.x, fp.y - dog.position.y };

	double a = fv.x * fv.x + fv.y * fv.y - dog.speed * dog.speed;
	double b = d.x * fv.x + d.y * fv.y;
	double c = d.x * d.x + d.y * d.y;
	double det = b * b - a * c;

	if (det < 0) return make_pair(INF, INF);

	double t1 = (-b + sqrt(det)) / a;
	double t2 = (-b - sqrt(det)) / a;
	double t  = min(POS_OR_INF(t1), POS_OR_INF(t2));

	if (t < 0 || t == INF) return make_pair(INF, INF);

	double rad = atan2(d.y + fv.y * t, d.x + fv.x * t);

	// check
	//double xf = fp.x + fv.x * t; double xd = d.position.x + d.speed * t * cos(rad);
	//double yf = fp.y + fv.y * t; double yd = d.position.y + d.speed * t * sin(rad);

	return make_pair(t, rad);
}


int main(int argc, char** argv) {
	while (1) {
		int N, M;
		cin >> N >> M;

		if (N == 0 && M == 0) break;

		vector<Dog> dogs(N);
		vector<int> frisbees(N);

		REP(i, N)
			cin >> dogs[i].position >> dogs[i].speed;

		REP(i, M) {
			Point fp, fv;
			vector<double> t(N), rad(N);

			cin >> fp >> fv;

			REP(j, N)
				tie(t[j], rad[j]) = solve(dogs[j], fp, fv);

			auto best = min_element(t.begin(), t.end());

			frisbees[best - t.begin()]++;

			// move dogs
			REP(j, N) {
				if (t[j] == INF) continue;
				dogs[j].position.x += dogs[j].speed * cos(rad[j]) * *best;
				dogs[j].position.y += dogs[j].speed * sin(rad[j]) * *best;
			}
		}

		REP(i, N)
			cout << frisbees[i] << (i == N - 1 ? "\n" : " ");
	}
}
accuracy: 1
time_ms: 140
memory_kb: 3548
final_rank: 13

code_snippet: #include <algorithm>
#include <iostream>
#include <vector>
#include <cmath>
#include <numeric>
#include <tuple>
#include <assert.h>

#define sqr(x) std::pow(x, 2.0)
#define INF 1e10
#define REP(i, n) for (int i = 0; i < n; i++)
#define POS_OR_INF(x) (x > 0 ? x : INF)

using namespace std;

struct Point {
	double x;
	double y;
};

inline istream& operator >> (istream& is, Point& p) {
	return is >> p.x >> p.y;
}

typedef Point Vector;

struct Dog {
	Point  position;
	double speed;
	int    n_frisbees;
};

inline std::pair<double, double> solve(const Dog& dog, const Point& fp, const Vector& fv) {
	Vector d = { fp.x - dog.position.x, fp.y - dog.position.y };

	double a = fv.x * fv.x + fv.y * fv.y - dog.speed * dog.speed;
	double b = d.x * fv.x + d.y * fv.y;
	double c = d.x * d.x + d.y * d.y;
	double det = b * b - a * c;

	if (det < 0) return make_pair(INF, INF);

	double t1 = (-b + sqrt(det)) / a;
	double t2 = (-b - sqrt(det)) / a;
	double t  = min(POS_OR_INF(t1), POS_OR_INF(t2));

	if (t < 0 || t == INF) return make_pair(INF, INF);

	double rad = atan2(d.y + fv.y * t, d.x + fv.x * t);

	// check
	//double xf = fp.x + fv.x * t; double xd = d.position.x + d.speed * t * cos(rad);
	//double yf = fp.y + fv.y * t; double yd = d.position.y + d.speed * t * sin(rad);

	return make_pair(t, rad);
}


int main(int argc, char** argv) {
	while (1) {
		int N, M;
		cin >> N >> M;

		if (N == 0 && M == 0) break;

		vector<Dog> dogs(N);

		REP(i, N) {
			cin >> dogs[i].position >> dogs[i].speed;
			dogs[i].n_frisbees = 0;
		}

		REP(i, M) {
			Point fp, fv;
			vector<double> t(N), rad(N);

			cin >> fp >> fv;

			REP(j, N)
				tie(t[j], rad[j]) = solve(dogs[j], fp, fv);

			auto best = min_element(t.begin(), t.end());

			dogs[best - t.begin()].n_frisbees++;

			// move dogs
			REP(j, N) {
				if (t[j] == INF) continue;
				dogs[j].position.x += dogs[j].speed * cos(rad[j]) * *best;
				dogs[j].position.y += dogs[j].speed * sin(rad[j]) * *best;
			}
		}

		REP(i, N)
			cout << dogs[i].n_frisbees << (i == N - 1 ? "\n" : " ");
	}
}
accuracy: 1
time_ms: 140
memory_kb: 3676
final_rank: 17

code_snippet: #include <algorithm>
#include <iostream>
#include <vector>
#include <cmath>
#include <numeric>
#include <tuple>
#include <assert.h>

using namespace std;

struct Point {
	double x;
	double y;
};

inline istream& operator >> (istream& is, Point& p) {
	return is >> p.x >> p.y;
}

typedef Point Vector;

struct Dog {
	Point position;
	double speed;
	int n_frisbees;
};

#define sqr(x) std::pow(x, 2.0)
#define INF 1e10
#define REP(i, n) for (int i = 0; i < n; i++)

inline std::pair<double, double> solve(const Dog& d, const Point& fp, const Vector& fv) {
	double delta_x = fp.x - d.position.x;
	double delta_y = fp.y - d.position.y;

	double a = sqr(fv.x) + sqr(fv.y) - sqr(d.speed);
	double b = delta_x * fv.x + delta_y * fv.y;
	double c = sqr(delta_x) + sqr(delta_y);
	double det = sqr(b) - a * c;

	if (det < 0) {
		return make_pair(INF, INF);
	}
	double t1 = (-b + sqrt(sqr(b) - a * c)) / a;
	double t2 = (-b - sqrt(sqr(b) - a * c)) / a;

	t1 = t1 > 0 ? t1 : INF;
	t2 = t2 > 0 ? t2 : INF;

	double t = min(t1, t2);

	if (t < 0 || t == INF) {
		return make_pair(INF, INF);
	}

	double rad = atan2(delta_y + fv.y * t, delta_x + fv.x * t);

	// check
	//double xf = fp.x + fv.x * t; double xd = d.position.x + d.speed * t * cos(rad);
	//double yf = fp.y + fv.y * t; double yd = d.position.y + d.speed * t * sin(rad);

	return make_pair(t, rad);
}


int main(int argc, char** argv) {
	while (1) {
		int N, M;
		cin >> N >> M;

		if (N == 0 && M == 0) break;

		vector<Dog> dogs(N);

		REP(i, N) {
			cin >> dogs[i].position >> dogs[i].speed;
			dogs[i].n_frisbees = 0;
		}

		REP(i, M) {
			Point fp, fv;
			vector<double> t(N), rad(N);

			cin >> fp >> fv;

			REP(j, N)
				tie(t[j], rad[j]) = solve(dogs[j], fp, fv);

			auto best = min_element(t.begin(), t.end());

			dogs[best - t.begin()].n_frisbees++;

			// move dogs
			REP(j, N) {
				if (t[j] == INF)
					continue;
				dogs[j].position.x += dogs[j].speed * cos(rad[j]) * *best;
				dogs[j].position.y += dogs[j].speed * sin(rad[j]) * *best;
			}
		}

		for (int i = 0; i < N; i++)
			cout << dogs[i].n_frisbees << (i == N - 1 ? "\n" : " ");
	}
}
accuracy: 1
time_ms: 140
memory_kb: 3608
final_rank: 15

code_snippet: // aribon3-6_e
#include <bits/stdc++.h>
#ifdef LOCAL
#include "../cxx-prettyprint/prettyprint.hpp"
#endif
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> P;

#define REP(i, n) for (int (i) = 0 ; (i) < (int)(n) ; ++(i))
#define REPN(i, m, n) for (int (i) = m ; (i) < (int)(n) ; ++(i))
#define REP_REV(i, n) for (int (i) = (int)(n) - 1 ; (i) >= 0 ; --(i))
#define REPN_REV(i, m, n) for (int (i) = (int)(n) - 1 ; (i) >= m ; --(i))
#define ALL(x) x.begin(), x.end()

#define INF ((1 << 29)-1)
#define MOD (1000000007)

#define print2D(h, w, arr) REP(i, h) { REP(j, w) cout << arr[i][j] << " "; cout << endl; }
template<class T> void print(const T& x){cout << x << endl;}
template<class T, class... A> void print(const T& first, const A&... rest) { cout << first << " "; print(rest...); }
struct PreMain {PreMain(){cin.tie(0);ios::sync_with_stdio(false);cout<<fixed<<setprecision(20);}} premain;

// ベクトル
struct Point {
    constexpr static double eps = 1e-9;
    double x, y;
    explicit Point(double x=0, double y=0): x(x), y(y) {}
    Point& operator+=(const Point& v){ x += v.x; y+= v.y; return *this;}
    Point operator+(const Point& v) const{return Point(*this) += v;}
    Point& operator-=(const Point& v){x -= v.x; y-= v.y; return *this;}
    Point operator-(const Point& v) const{return Point(*this) -= v;}
    Point& operator*=(double s){x *= s; y *= s; return *this;}
    Point operator*(double s) const{return Point(*this) *= s;}
    Point& operator/=(double s){x /= s; y /= s; return *this;}
    Point operator/(double s) const{return Point(*this) /= s;}
    double dot(const Point& v) const {return x*v.x + y*v.y;}        /* 内積 */
    double cross(const Point& v) const {return x*v.y - v.x*y;}      /* 外積 */
    double norm2() const {return x*x + y*y;}                        /* ノルムの二乗*/
    double norm() const {return sqrt(norm2());}                     /* ノルム */
    int quadrant() const { if(y > 0) return x>0 ? 1:2; else return x>0 ? 4:3;} /* 象限判定 */

    friend ostream& operator<<(ostream& os, const Point& v) {os<<"("<<v.x<<","<<v.y<<")"; return os;}
    friend istream& operator>>(istream& is, Point& v){ is >> v.x >> v.y; return is;}

    // 点a, b, cからなる三角形の面積
    friend double calc_triangle_area(Point a, Point b, Point c) {
        Point v1 = b - a;
        Point v2 = c - a;
        return abs(v1.cross(v2)) / 2;
    }

    // 点a, bを通る直線と点cとの距離
    friend double calc_distance_between_point_and_line(Point a, Point b, Point c) {
        return abs((b-a).cross(c-a)) / (b-a).norm();
    }

    // 点a, bを端点とする線分と点cとの距離
    friend double calc_distance_between_point_and_segment(Point a, Point b, Point c) {
        if ((b-a).dot(c-a) < eps) return (c-a).norm();
        if ((a-b).dot(c-b) < eps) return (c-b).norm();
        return calc_distance_between_point_and_line(a, b, c);
    }

    // 点a, bを端点とする線分と点cと点dを端点とする線分の距離
    friend double calc_distance_between_segments(Point a, Point b, Point c, Point d) {
        double d0 = calc_distance_between_point_and_segment(a, b, c);
        double d1 = calc_distance_between_point_and_segment(a, b, d);
        double d2 = calc_distance_between_point_and_segment(c, d, a);
        double d3 = calc_distance_between_point_and_segment(c, d, b);
        return min(min(d0, d1), min(d2, d3));
    }

    enum RELATION_BETWEEN_SEGMENT_AND_POINT {
        COUNTER_CLOCKWISE = 1,     // p1とp2のp0を挟んだ位置関係が反時計回り
        CLOCKWISE = -1,            // 時計回り
        ONLINE_BACK = 2,           // p1とp2がp0を挟んで直線状にある
        ONLINE_FRONT = -2,         // p0とp2の間にp1がある
        ON_SEGMENT = 0,            // p0とp1の間にp2がある
    };

    // 点cが点a, bを端点とする線分のどちら側にあるか、enumで返す
    friend RELATION_BETWEEN_SEGMENT_AND_POINT ccw_ex(Point p0, Point p1, Point p2) {
        Point v1 = p1 - p0;
        Point v2 = p2 - p0;
        if(v1.cross(v2) > eps) return COUNTER_CLOCKWISE;    // 1
        if(v1.cross(v2) < -eps) return CLOCKWISE;           // -1
        if(v1.dot(v2) < -eps) return ONLINE_BACK;           // 2
        if(v1.norm() < v2.norm()) return ONLINE_FRONT;      // -2
        return ON_SEGMENT;                                  // 0
    }

    // 点cが点a, bを端点とする線分のどちら側にあるか
    friend int ccw(Point p0, Point p1, Point p2) {
        Point v1 = p1 - p0;
        Point v2 = p2 - p0;
        if(v1.cross(v2) > eps) return 1;
        if(v1.cross(v2) < -eps) return -1;
        return 0;
    }

    // p1,p2を端点とする線分Aとp3,p4を端点とする線分Bの交差判定
    // include_end=trueなら端点が重なっていても交差しているとみなす
    friend bool intersect(Point p1, Point p2, Point p3, Point p4, bool include_end=true) {

        bool is_otherside;
        bool is_inside;

        if (include_end){
            is_otherside = ccw(p1,p2,p3) * ccw(p1,p2,p4) <= 0; // Aの両側にBの端点があるかどうか。どちらかがAの直線状にいてもOK
            is_inside = ccw(p3,p4,p1) * ccw(p3,p4,p2) <= 0;    // Aの端点の内側にBがいるかどうか。
        } else {
            is_otherside = ccw(p1,p2,p3) * ccw(p1,p2,p4) < 0; // Aの両側にBの端点があるかどうか
            is_inside = ccw(p3,p4,p1) * ccw(p3,p4,p2) < 0;    // Aの端点の内側にBがいるかどうか
        }
        return is_otherside && is_inside;
    }

};

// 円
struct Circle {
    Point c;
    double r;
    Circle(){}
    Circle(Point c, double r):c(c),r(r){}
};


int main() {
#ifdef LOCAL
    ifstream in("../in.txt"); cin.rdbuf(in.rdbuf());
#endif

    while (true) {
        int N, M;
        cin >> N >> M;
        if (N == 0 && M == 0) break;

        vector<Point> dog_pos(N);
        vector<double> dog_speed(N);
        vector<Point> frisbee_pos(M);
        vector<Point> frisbee_V(M);

        REP(i, N) cin >> dog_pos[i] >> dog_speed[i];
        REP(i, M) cin >> frisbee_pos[i] >> frisbee_V[i];

        vector<int> dog_score(N);
        REP(fid, M) {

            vector<Point> dog_V(N);
            double min_t = numeric_limits<double>::max();
            int min_did = -1;
            REP(did, N) {

                Point rel_pos = dog_pos[did] - frisbee_pos[fid];
                double p_2 = rel_pos.norm2();
                double p_dot_vf = rel_pos.dot(frisbee_V[fid]);

                double Vf_2 = frisbee_V[fid].norm2();
                double Vd_2 = dog_speed[did] * dog_speed[did];

                double a = Vf_2 - Vd_2;
                double b = - 2 * p_dot_vf;
                double c = p_2;

                double t;
                if (abs(a) < Point::eps) {
                    t = - c / b;
                } else {
                    double D = b * b - 4 * a * c;
                    if (D < 0){
                        t = numeric_limits<double>::max();
                    } else {
                        D = sqrt(D);
                        double t1 = (-b - D) / (2 * a);
                        double t2 = (-b + D) / (2 * a);
                        if (t1 > t2) swap(t1, t2);
                        t = t1 > Point::eps ? t1 : t2 > Point::eps ? t2 : numeric_limits<double>::max();
                    }
                }

                if (t < min_t) {
                    min_t = t;
                    min_did = did;
                }

                Point intersection = frisbee_pos[fid] + frisbee_V[fid] * t;
                dog_V[did] = (intersection - dog_pos[did]) / t;
                if (t == numeric_limits<double>::max()) dog_V[did] = Point(0, 0);

            }

            dog_score[min_did]++;

            REP(did, N){
                dog_pos[did] += dog_V[did] * min_t;
            }
        }

        REP(did, N-1) {
            cout << dog_score[did] << " ";
        }
        print(dog_score[N-1]);

    }


    return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 3200
final_rank: 5

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define int long long
#define FOR(i, a, b) for(ll i = (a); i < (b); ++i)
#define FORR(i, a, b) for(ll i = (a); i > (b); --i)
#define REP(i, n) for(ll i = 0; i < (n); ++i)
#define REPR(i, n) for(ll i = n; i >= 0; i--)
#define FOREACH(x, a) for(auto &(x) : (a))
#define VECCIN(x)                                                              \
    for(auto &youso_ : (x)) cin >> youso_
#define bitcnt __builtin_popcount
#define SZ(x) ((ll)(x).size())
#define fi first
#define se second
#define All(a) (a).begin(), (a).end()
template <typename T = long long> inline T IN() {
    T x;
    cin >> x;
    return (x);
}
inline void CIN() {}
template <class Head, class... Tail>
inline void CIN(Head &&head, Tail &&... tail) {
    cin >> head;
    CIN(move(tail)...);
}
#define CCIN(...)                                                              \
    char __VA_ARGS__;                                                          \
    CIN(__VA_ARGS__)
#define DCIN(...)                                                              \
    double __VA_ARGS__;                                                        \
    CIN(__VA_ARGS__)
#define LCIN(...)                                                              \
    ll __VA_ARGS__;                                                            \
    CIN(__VA_ARGS__)
#define SCIN(...)                                                              \
    string __VA_ARGS__;                                                        \
    CIN(__VA_ARGS__)
#define Printv(v)                                                              \
    {                                                                          \
        REP(x, v.size()) { cout << v[x] << (x == v.size() - 1 ? "\n" : " "); } \
    }
template <typename T = string> inline void eputs(T s) {
    cout << s << "\n";
    exit(0);
}
template <typename A, size_t N, typename T>
void Fill(A (&array)[N], const T &val) {
    std::fill((T *)array, (T *)(array + N), val);
}
template <typename T> using PQG = priority_queue<T, vector<T>, greater<T>>;
template <typename T> using PQ = priority_queue<T>;

typedef long long ll;
typedef vector<ll> VL;
typedef vector<VL> VVL;
typedef pair<ll, ll> PL;

const int INF = 1e9;
const int MOD = 1e9 + 7;
const double PI = atan(1.0) * 4.0;
// const int MOD = 998244353;
const ll LINF = 1e18;
const ll dx[] = {1, 0, -1, 0};
const ll dy[] = {0, 1, 0, -1};

void cinfast() {
    cin.tie(0);
    ios::sync_with_stdio(false);
}

/* 基本要素 */

typedef double D;     // 座標値の型。doubleかlong doubleを想定
typedef complex<D> P; // Point
typedef pair<P, P> L; // Line
typedef vector<P> VP;
const D EPS = 1e-9; // 許容誤差。問題によって変える;

#define X real()
#define Y imag()
#define LE(n, m) ((n) < (m) + EPS)
#define GE(n, m) ((n) + EPS > (m))
#define EQ(n, m) (abs((n) - (m)) < EPS)

// 内積　dot(a,b) = |a||b|cosθ
D dot(P a, P b) { return (conj(a) * b).X; }
// 外積　cross(a,b) = |a||b|sinθ
D cross(P a, P b) { return (conj(a) * b).Y; }

// 点の進行方向
int ccw(P a, P b, P c) {
    b -= a;
    c -= a;
    if(cross(b, c) > EPS) return +1;  // counter clockwise
    if(cross(b, c) < -EPS) return -1; // clockwise
    if(dot(b, c) < -EPS) return +2;   // c--a--b on line
    if(norm(b) < norm(c)) return -2;  // a--b--c on line or a==b
    return 0;                         // a--c--b on line or a==c or b==c
}

/* 交差判定　直線・線分は縮退してはならない。接する場合は交差するとみなす。isecはintersectの略
 */

// 直線と点
bool isecLP(P a1, P a2, P b) {
    return abs(ccw(a1, a2, b)) != 1; // return EQ(cross(a2-a1, b-a1), 0); と等価
}

// 直線と直線
bool isecLL(P a1, P a2, P b1, P b2) {
    return !isecLP(a2 - a1, b2 - b1, 0) || isecLP(a1, b1, b2);
}

// 直線と線分
bool isecLS(P a1, P a2, P b1, P b2) {
    return cross(a2 - a1, b1 - a1) * cross(a2 - a1, b2 - a1) < EPS;
}

// 線分と線分
bool isecSS(P a1, P a2, P b1, P b2) {
    return ccw(a1, a2, b1) * ccw(a1, a2, b2) <= 0 &&
           ccw(b1, b2, a1) * ccw(b1, b2, a2) <= 0;
}

// 線分と点
bool isecSP(P a1, P a2, P b) { return !ccw(a1, a2, b); }

/* 距離　各直線・線分は縮退してはならない */

// 点pの直線aへの射影点を返す
P proj(P a1, P a2, P p) {
    if(a1 == a2) eputs("same points");
    return a1 + dot(a2 - a1, p - a1) / norm(a2 - a1) * (a2 - a1);
}

// 点pの直線aへの反射点を返す
P reflection(P a1, P a2, P p) { return 2.0 * proj(a1, a2, p) - p; }

D distLP(P a1, P a2, P p) { return abs(proj(a1, a2, p) - p); }

D distLL(P a1, P a2, P b1, P b2) {
    return isecLL(a1, a2, b1, b2) ? 0 : distLP(a1, a2, b1);
}

D distLS(P a1, P a2, P b1, P b2) {
    return isecLS(a1, a2, b1, b2) ? 0
                                  : min(distLP(a1, a2, b1), distLP(a1, a2, b2));
}

D distSP(P a1, P a2, P p) {
    P r = proj(a1, a2, p);
    if(isecSP(a1, a2, r)) return abs(r - p);
    return min(abs(a1 - p), abs(a2 - p));
}

D distSS(P a1, P a2, P b1, P b2) {
    if(isecSS(a1, a2, b1, b2)) return 0;
    return min(min(distSP(a1, a2, b1), distSP(a1, a2, b2)),
               min(distSP(b1, b2, a1), distSP(b1, b2, a2)));
}

// 2直線の交点
P crosspointLL(P a1, P a2, P b1, P b2) {
    D d1 = cross(b2 - b1, b1 - a1);
    D d2 = cross(b2 - b1, a2 - a1);
    if(EQ(d1, 0) && EQ(d2, 0)) return a1; // same line
    if(EQ(d2, 0)) throw "kouten ga nai";  // 交点がない
    return a1 + d1 / d2 * (a2 - a1);
}

/* 円 */

D distLC(P a1, P a2, P c, D r) { return max(distLP(a1, a2, c) - r, 0.0); }

D distSC(P a1, P a2, P c, D r) {
    D dSqr1 = norm(c - a1), dSqr2 = norm(c - a2);
    if(dSqr1 < r * r ^ dSqr2 < r * r)
        return 0; // 円が線分を包含するとき距離0ならここをORに変える
    if(dSqr1 < r * r & dSqr2 < r * r) return r - sqrt(max(dSqr1, dSqr2));
    return max(distSP(a1, a2, c) - r, 0.0);
}

VP crosspointLC(P a1, P a2, P c, D r) {
    VP ps;
    P ft = proj(a1, a2, c);
    if(!GE(r * r, norm(ft - c))) return ps;

    P dir = sqrt(max(r * r - norm(ft - c), 0.0)) / abs(a2 - a1) * (a2 - a1);
    ps.push_back(ft + dir);
    if(!EQ(r * r, norm(ft - c))) ps.push_back(ft - dir);
    return ps;
}

D distCC(P a, D ar, P b, D br) {
    D d = abs(a - b);
    return GE(d, abs(ar - br)) ? max(d - ar - br, 0.0) : abs(ar - br) - d;
}

// 2円の交点
VP crosspointCC(P a, D ar, P b, D br) {
    VP ps;
    P ab = b - a;
    D d = abs(ab);
    D crL = (norm(ab) + ar * ar - br * br) / (2 * d);
    if(EQ(d, 0) || ar < abs(crL)) return ps;

    P abN = ab * P(0, sqrt(ar * ar - crL * crL) / d);
    P cp = a + crL / d * ab;
    ps.push_back(cp + abN);
    if(!EQ(norm(abN), 0)) ps.push_back(cp - abN);
    return ps;
}

// 点pから円aへの接線の接点
VP tangentPoints(P a, D ar, P p) {
    VP ps;
    D sin = ar / abs(p - a);
    if(!LE(sin, 1)) return ps; // ここでNaNも弾かれる
    D t = 2 * PI - asin(min(sin, 1.0));
    ps.push_back(a + (p - a) * polar(sin, t));
    if(!EQ(sin, 1)) ps.push_back(a + (p - a) * polar(sin, -t));
    return ps;
}

// 2円の共通接線。返される各直線に含まれる頂点は円との接点となる
vector<L> tangentLines(P a, D ar, P b, D br) {
    vector<L> ls;
    D d = abs(b - a);
    REP(i, 2) {
        D sin = (ar - (1 - i * 2) * br) / d;
        if(!LE(sin * sin, 1)) break;
        D cos = sqrt(max(1 - sin * sin, 0.0));
        REP(j, 2) {
            P n = (b - a) * P(sin, (1 - j * 2) * cos) / d;
            ls.push_back(L(a + ar * n, b + (1 - i * 2) * br * n));
            if(cos < EPS)
                break; // 重複する接線を無視（重複していいならこの行不要）
        }
    }
    return ls;
}

// 三角形の外心。点a,b,cは同一線上にあってはならない
P circumcenter(P a, P b, P c) {
    a = (a - c) * 0.5;
    b = (b - c) * 0.5;
    return c + crosspointLL(a, a * P(1, 1), b, b * P(1, 1));
}

// 点aと点bを通り、半径がrの円の中心を返す
VP circlesPointsRadius(P a, P b, D r) {
    VP cs;
    P abH = (b - a) * 0.5;
    D d = abs(abH);
    if(d == 0 || d > r)
        return cs; // 必要なら !LE(d,r) として円1つになる側へ丸める
    D dN = sqrt(r * r - d * d); // 必要なら max(r*r - d*d, 0) とする
    P n = abH * P(0, 1) * (dN / d);
    cs.push_back(a + abH + n);
    if(dN > 0) cs.push_back(a + abH - n);
    return cs;
}

// 点aと点bを通り、直線lに接する円の中心
VP circlesPointsTangent(P a, P b, P l1, P l2) {
    P n = (l2 - l1) * P(0, 1);
    P m = (b - a) * P(0, 0.5);
    D rC = dot((a + b) * 0.5 - l1, n);
    D qa = norm(n) * norm(m) - dot(n, m) * dot(n, m);
    D qb = -rC * dot(n, m);
    D qc = norm(n) * norm(m) - rC * rC;
    D qd = qb * qb - qa * qc; // qa*k^2 + 2*qb*k + qc = 0

    VP cs;
    if(qd < -EPS) return cs;
    if(EQ(qa, 0)) {
        if(!EQ(qb, 0)) cs.push_back((a + b) * 0.5 - m * (qc / qb / 2));
        return cs;
    }
    D t = -qb / qa;
    cs.push_back((a + b) * 0.5 + m * (t + sqrt(max(qd, 0.0)) / qa));
    if(qd > EPS)
        cs.push_back((a + b) * 0.5 + m * (t - sqrt(max(qd, 0.0)) / qa));
    return cs;
}

// 点集合を含む最小の円の中心
P minEnclosingCircle(const VP &ps) {
    P c;
    double move = 0.5;
    REP(i, 39) { // 2^(-39-1) \approx 0.9e-12
        REP(t, 50) {
            D max = 0;
            int k = 0;
            REP(j, ps.size()) if(max < norm(ps[j] - c)) {
                max = norm(ps[j] - c);
                k = j;
            }
            c += (ps[k] - c) * move;
        }
        move /= 2;
    }
    return c;
}

/* 多角形 */

// 頂点の順序（sortやmax_elementに必要）
namespace std {
bool operator<(const P a, const P b) {
    return a.X != b.X ? a.X < b.X : a.Y < b.Y;
}
} // namespace std

// 凸包
VP convexHull(VP ps) { // 元の点集合がソートされていいならVP&に
    int n = ps.size(), k = 0;
    sort(ps.begin(), ps.end());
    VP ch(2 * n);
    for(int i = 0; i < n; ch[k++] = ps[i++]) // lower-hull
        while(k >= 2 && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0)
            --k; // 余計な点も含むなら == -1 とする
    for(int i = n - 2, t = k + 1; i >= 0; ch[k++] = ps[i--]) // upper-hull
        while(k >= t && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
    ch.resize(k - 1);
    return ch;
}

// 凸判定。縮退を認めないならccwの判定部分を != 1 とする
bool isCcwConvex(const VP &ps) {
    int n = ps.size();
    REP(i, n)
    if(ccw(ps[i], ps[(i + 1) % n], ps[(i + 2) % n]) == -1) return false;
    return true;
}

// 凸多角形の内部判定　O(n)
// 点が領域内部なら1、境界上なら2、外部なら0を返す
int inConvex(P p, const VP &ps) {
    int n = ps.size();
    int dir = ccw(ps[0], ps[1], p);
    REP(i, n) {
        int ccwc = ccw(ps[i], ps[(i + 1) % n], p);
        if(!ccwc) return 2; // 線分上に存在
        if(ccwc != dir) return 0;
    }
    return 1;
}

// 凸多角形の内部判定　O(logn)
// 点が領域内部なら1、境界上なら2、外部なら0を返す
int inCcwConvex(const VP &ps, P p) {
    int n = ps.size();
    P g = (ps[0] + ps[n / 3] + ps[n * 2 / 3]) / 3.0;
    if(g == p) return 1;
    P gp = p - g;

    int l = 0, r = n;
    while(l + 1 < r) {
        int mid = (l + r) / 2;
        P gl = ps[l] - g;
        P gm = ps[mid] - g;
        if(cross(gl, gm) > 0) {
            if(cross(gl, gp) >= 0 && cross(gm, gp) <= 0)
                r = mid;
            else
                l = mid;
        } else {
            if(cross(gl, gp) <= 0 && cross(gm, gp) >= 0)
                l = mid;
            else
                r = mid;
        }
    }
    r %= n;
    D cr = cross(ps[l] - p, ps[r] - p);
    return EQ(cr, 0) ? 2 : cr < 0 ? 0 : 1;
}

// 多角形の内部判定
// 点が領域内部なら1、境界上なら2、外部なら0を返す
int inPolygon(const VP &ps, P p) {
    int n = ps.size();
    bool in = false;
    REP(i, n) {
        P a = ps[i] - p;
        P b = ps[(i + 1) % n] - p;
        if(EQ(cross(a, b), 0) && LE(dot(a, b), 0)) return 2;
        if(a.Y > b.Y) swap(a, b);
        if((a.Y * b.Y < 0 || (a.Y * b.Y < EPS && b.Y > EPS)) &&
           LE(cross(a, b), 0))
            in = !in;
    }
    return in;
}

// 凸多角形クリッピング
VP convexCut(const VP &ps, P a1, P a2) {
    int n = ps.size();
    VP ret;
    REP(i, n) {
        int ccwc = ccw(a1, a2, ps[i]);
        if(ccwc != -1) ret.push_back(ps[i]);
        int ccwn = ccw(a1, a2, ps[(i + 1) % n]);
        if(ccwc * ccwn == -1)
            ret.push_back(crosspointLL(a1, a2, ps[i], ps[(i + 1) % n]));
    }
    return ret;
}

// 凸多角形の直径（最遠点対）
pair<int, int> convexDiameter(const VP &ps) {
    int n = ps.size();
    int i = min_element(ps.begin(), ps.end()) - ps.begin();
    int j = max_element(ps.begin(), ps.end()) - ps.begin();
    int maxI, maxJ;
    D maxD = 0;
    REP(_, 2 * n) {
        if(maxD < norm(ps[i] - ps[j])) {
            maxD = norm(ps[i] - ps[j]);
            maxI = i;
            maxJ = j;
        }
        if(cross(ps[i] - ps[(i + 1) % n], ps[(j + 1) % n] - ps[j]) <= 0)
            j = (j + 1) % n;
        else
            i = (i + 1) % n;
    }
    return make_pair(maxI, maxJ);
}

// 多角形の符号付面積
D area(const VP &ps) {
    D a = 0;
    REP(i, ps.size()) a += cross(ps[i], ps[(i + 1) % ps.size()]);
    return a / 2;
}

// 多角形の幾何学的重心
P centroid(const VP &ps) {
    int n = ps.size();
    D aSum = 0;
    P c;
    REP(i, n) {
        D a = cross(ps[i], ps[(i + 1) % n]);
        aSum += a;
        c += (ps[i] + ps[(i + 1) % n]) * a;
    }
    return 1 / aSum / 3 * c;
}

// ボロノイ領域
VP voronoiCell(P p, const VP &ps, const VP &outer) {
    VP cl = outer;
    REP(i, ps.size()) {
        if(EQ(norm(ps[i] - p), 0)) continue;
        P h = (p + ps[i]) * 0.5;
        cl = convexCut(cl, h, h + (ps[i] - h) * P(0, 1));
    }
    return cl;
}

/* 幾何グラフ */

struct Edge {
    int from, to;
    D cost;
    Edge(int from, int to, D cost) : from(from), to(to), cost(cost) {}
};
struct Graph {
    int n;
    vector<vector<Edge>> edges;
    Graph(int n) : n(n), edges(n) {}
    void addEdge(Edge e) {
        edges[e.from].push_back(e);
        edges[e.to].push_back(Edge(e.to, e.from, e.cost));
    }
};

// 線分アレンジメント（線分の位置関係からグラフを作成）
Graph segmentArrangement(const vector<L> &segs, VP &ps) {
    int n = segs.size();
    REP(i, n) {
        ps.push_back(segs[i].first);
        ps.push_back(segs[i].second);
        REP(j, i) {
            if(isecSS(segs[i].first, segs[i].second, segs[j].first,
                      segs[j].second))
                ps.push_back(crosspointLL(segs[i].first, segs[i].second,
                                          segs[j].first, segs[j].second));
        }
    }
    sort(ps.begin(), ps.end());
    ps.erase(unique(ps.begin(), ps.end()), ps.end());

    int m = ps.size();
    Graph gr(m);
    vector<pair<D, int>> list;
    REP(i, n) {
        list.clear();
        REP(j, m) {
            if(isecSP(segs[i].first, segs[i].second, ps[j]))
                list.push_back(make_pair(norm(segs[i].first - ps[j]), j));
        }
        sort(list.begin(), list.end());
        REP(j, list.size() - 1) {
            int a = list[j].second;
            int b = list[j + 1].second;
            gr.addEdge(Edge(a, b, abs(ps[a] - ps[b])));
        }
    }
    return gr;
}

// 可視グラフ（点集合から見える位置へ辺を張ったグラフ）
Graph visibilityGraph(const VP &ps, const vector<VP> &objs) {
    int n = ps.size();
    Graph gr(n);
    REP(i, n) REP(j, i) {
        P a = ps[i], b = ps[j];
        if(!EQ(norm(a - b), 0)) REP(k, objs.size()) {
                const VP &obj = objs[k];
                int inStA = inConvex(a, obj);
                int inStB = inConvex(b, obj);
                if((inStA ^ inStB) % 2 ||
                   inStA * inStB != 1 && inConvex((a + b) * 0.5, obj) == 1)
                    goto skip;
                REP(l, obj.size()) {
                    P cur = obj[l];
                    P next = obj[(l + 1) % obj.size()];
                    if(isecSS(a, b, cur, next) && !isecSP(cur, next, a) &&
                       !isecSP(cur, next, b))
                        goto skip;
                }
            }
        gr.addEdge(Edge(i, j, abs(a - b)));
    skip : {}
    }
    return gr;
}

/* その他 */

// 重複する線分を併合する
vector<L> mergeSegments(vector<L> segs) {
    int n = segs.size();
    REP(i, n)
    if(segs[i].second < segs[i].first) swap(segs[i].second, segs[i].first);

    REP(i, n) REP(j, i) {
        L &l1 = segs[i], &l2 = segs[j];
        if(EQ(cross(l1.second - l1.first, l2.second - l2.first), 0) &&
           isecLP(l1.first, l1.second, l2.first) &&
           ccw(l1.first, l1.second, l2.second) != 2 &&
           ccw(l2.first, l2.second, l1.second) != 2) {
            segs[j] = L(min(l1.first, l2.first), max(l1.second, l2.second));
            segs[i--] = segs[--n];
            break;
        }
    }
    segs.resize(n);
    return segs;
}

inline double pp2(P a) { return a.X * a.X + a.Y * a.Y; }
inline double p2(double a) { return a * a; }
double pow2(double a) { return a * a; }

signed main() {
    for(;;) {
        int n, m;
        cin >> n >> m;
        if(n == 0) return 0;

        vector<double> x(n), y(n), v(n);
        for(int i = 0; i < n; ++i) cin >> x[i] >> y[i] >> v[i];

        vector<int> num(n, 0);
        while(--m >= 0) {
            double fpx, fpy, fvx, fvy;
            cin >> fpx >> fpy >> fvx >> fvy;

            vector<double> vy(n, 0.0), vx(n, 0.0);
            double minT = DBL_MAX;
            int getDog;
            for(int i = 0; i < n; ++i) {
                double a = pow2(fvx) + pow2(fvy) - pow2(v[i]);
                double b = 2 * (fvx * (fpx - x[i]) + fvy * (fpy - y[i]));
                double c = pow2(fpx - x[i]) + pow2(fpy - y[i]);
                double d = pow2(b) - 4 * a * c;
                if(d >= 0.0) {
                    double t;
                    if(fabs(a) < EPS) {
                        t = -c / b;
                        if(t < 0.0) continue;
                    } else {
                        double tmp = (-b - sqrt(d)) / (2 * a);
                        if(tmp >= 0.0)
                            t = tmp;
                        else {
                            tmp = (-b + sqrt(d)) / (2 * a);
                            if(tmp >= 0.0)
                                t = tmp;
                            else
                                continue;
                        }
                    }
                    vx[i] = (fpx - x[i] + fvx * t) / t;
                    vy[i] = (fpy - y[i] + fvy * t) / t;
                    if(t < minT) {
                        minT = t;
                        getDog = i;
                    }
                }
            }

            ++num[getDog];
            for(int i = 0; i < n; ++i) {
                x[i] += vx[i] * minT;
                y[i] += vy[i] * minT;
            }
        }

        Printv(num)
    }
}
accuracy: 1
time_ms: 100
memory_kb: 3100
final_rank: 4

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <cmath>

#define REP(i, a, b) for (int i = int(a); i < int(b); i++)
#ifdef _DEBUG_
#define dump(val) cerr << __LINE__ << ":\t" << #val << " = " << (val) << endl
#else
#define dump(val)
#endif

using namespace std;

typedef long long int ll;

template<typename T>
vector<T> make_v(size_t a, T b) {
    return vector<T>(a, b);
}

template<typename... Ts>
auto make_v(size_t a, Ts... ts) {
    return vector<decltype(make_v(ts...))>(a, make_v(ts...));
}

// 負なら追い付ける
double Dist(double dx, double dy, double fx, double fy, double v) {
    return hypot(dx - fx, dy - fy) - v;
}

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    const double inf = 1e+15;
    const double eps = 1e-6;
    int n, m;
    while (cin >> n >> m, n + m) {
        vector<double> Dx(n), Dy(n), V(n);
        REP(i, 0, n) {
            cin >> Dx[i] >> Dy[i] >> V[i];
        }
        vector<int> ans(n, 0);
        REP(_, 0, m) {
            double fx, fy, fvx, fvy;
            cin >> fx >> fy >> fvx >> fvy;
            double minT = inf;
            int minI = 0;
            vector<bool> get(n, false);
            vector<double> T(n, inf);
            vector<double> X(n, inf), Y(n, inf);
            REP(i, 0, n) {
                // 3分探索
                {
                    double l = 0, r = inf, t = 0;
                    REP (__, 0, 100) {
                        double m1 = (2 * l + r) / 3, m2 = (l + 2 * r) / 3;
                        double dist1 = Dist(Dx[i], Dy[i], fx + fvx * m1, fy + fvy * m1, V[i] * m1);
                        double dist2 = Dist(Dx[i], Dy[i], fx + fvx * m2, fy + fvy * m2, V[i] * m2);
                        if (dist1 > dist2) {
                            l = m1;
                            t = min(t, dist2);
                            T[i] = m2;
                        } else {
                            r = m2;
                            t = min(t, dist1);
                            T[i] = m1;
                        }
                        //cerr << T[i] << endl;
                    }
                    get[i] = (t < 0);
                }

                //2分探索
                if (get[i]) {
                    double l = 0, r = T[i];
                    REP (__, 0, 100) {
                        double mid = (l + r) / 2;
                        double dist = Dist(Dx[i], Dy[i], fx + fvx * mid, fy + fvy * mid, V[i] * mid);
                        //cerr << "?" << dist << endl;
                        if (dist < eps) {
                            get[i] = true;
                            T[i] = mid;
                            r = mid;
                            X[i] = fx + fvx * mid - Dx[i];
                            Y[i] = fy + fvy * mid - Dy[i];
                        } else {
                            l = mid;
                        }
                    }

                    //cerr << "!" << get[i] << " " << t << endl;
                    if (get[i] && T[i] + eps < minT) {
                        minT = T[i];
                        minI = i;
                    }
                }
            }

            //cerr << "!" << minT << " " << minI << endl;

            ans[minI]++;
            REP(i, 0, n) {
                if (get[i]) {
                    Dx[i] += minT / T[i] * X[i];
                    Dy[i] += minT / T[i] * Y[i];
                }
                //cerr << "ps" << Dx[i] << " " << Dy[i] << endl;
            }
        }
        REP(i, 0, n) {
            cout << ans[i] << " \n"[i + 1 == n];
        }
        cout << flush;
    }
    return 0;
}
accuracy: 1
time_ms: 2220
memory_kb: 3284
final_rank: 20

code_snippet: #include<cstdio>
#include<vector>
#include<queue>
#include<map>
#include<unordered_map>
#include<stack>
#include<string>
#include<algorithm>
#include<functional>
#include<cstring>
#include<complex>
using namespace std;

/**** Type Define ****/

typedef long long ll;
typedef pair<ll, ll> P;
typedef pair<ll, P> Q;
typedef complex<double> C;

/**** Macro Define ****/

#define cx real()
#define cy imag()

/**** Const List   ****/

const ll INF = 1LL << 60;
const ll mod = 1000000007;
const ll MAX_FLOW_MAX_V = 10000;
const ll MIN_COST_FLOW_MAX_V = 10000;
const ll BIPARTITE_MATCHING_MAX_V = 10000;
const ll dx[4] = {1, 0, -1, 0};
const ll dy[4] = {0, -1, 0, 1};
const C I = C(0, 1);
const double EPS = 1e-10;

/**** General Functions ****/

template <typename T>
T tmin(T a, T b) { return a > b ? b : a; };

template <typename T>
T tmax(T a, T b) { return a > b ? a : b; };

template <typename T>
T tadd(T a, T b) { return a + b; };

template <typename T>
T tmul(T a, T b) { return a * b; };

template <typename T>
T tpow(T a, T b) { return a * b; };

ll gcd(ll a, ll b) {
  if (b == 0) return a;
  return gcd(b, a % b);
}

ll extgcd(ll a, ll b, ll& x, ll& y) {
  if (b == 0) {
    x = 1, y = 0; return a;
  }
  ll q = a/b, g = extgcd(b, a - q*b, x, y);
  ll z = x - q * y;
  x = y;
  y = z;
  return g;
}

ll invmod (ll a, ll m) { // a^-1 mod m
  ll x, y;
  extgcd(a, m, x, y);
  x %= m;
  if (x < 0) x += m;
  return x;
}

ll nCk(ll n, ll k, ll mod) {
  ll ans = 1;
  for (ll i = n, j = 1; j <= k; i--, j++) ans = (((ans * i) % mod) * invmod(j, mod)) % mod;
  return ans;
}

ll lmin(ll a, ll b) { return a > b ? b : a; };

ll lmax(ll a, ll b) { return a > b ? a : b; };

ll lsum(ll a, ll b) { return a + b; };

/**** Matrix ****/

template <typename T>
struct Matrix {
  typedef vector<T> vec;
  typedef vector<vec> mat;
  ll x, y; // x: horizon  y: vertical
  mat d;

  Matrix(ll _y, ll _x = -1) {
    if (_x == -1) _x = _y;
    x = _x, y = _y;
    for (int i = 0; i < y; i++) for (int j = 0; j < x; j++) d[i][j] = 0;
  }
  void unit() {
    for (int i = 0; i < y; i++) for (int j = 0; j < x; j++) d[i][j] = i == j ? 1 : 0;
  }
  Matrix copy() {
    Matrix m(y, x);
    for (int i = 0; i < y; i++) for (int j = 0; j < x; j++) m.d[i][j] = d[i][j];
    return m;
  }
  Matrix<T> operator + (Matrix<T>& t) { // No error check! Don't forget to check Matrix size!!
    Matrix<T> m(y, x);
    for (int i = 0; i < y; i++) for (int j = 0; j < x; j++) m.d[i][j] = d[i][j] + t.d[i][j];
    return m;
  }
  Matrix<T> operator - (Matrix<T>& t) {
    Matrix<T> m(y, x);
    for (int i = 0; i < y; i++) for (int j = 0; j < x; j++) m.d[i][j] = d[i][j] - t.d[i][j];
    return m;
  }
  Matrix<T> operator * (T t) {
    Matrix<T> m(y, x);
    for (int i = 0; i < y; i++) for (int j = 0; j < x; j++) m.d[i][j] = d[i][j] * t;
    return m;
  }
  Matrix<T> det(Matrix<T>& t) { // x need to correspond to t.y
    Matrix<T> m(y, x);
    for (int i = 0; i < y; i++)
      for (int j = 0; j < x; j++)
        for (int k = 0; k < t.x; k++) m.d[i][j] += d[i][k] * t.d[k][j]; ////////////// mod???
    return m;
  }
};

/**** Zip ****/

template <typename T>
class Zip {
  vector<T> d;
  bool flag;
public:
  Zip() {
    flag = false;
  }
  void add(T x) {
    d.push_back(x);
    flag = true;
  }
  ll getNum(T x) { // T need to have operator < !!
    if (flag) {
      sort(d.begin(), d.end());
      d.erase(unique(d.begin(), d.end()), d.end());
      flag = false;
    }
    return lower_bound(d.begin(), d.end(), x) - d.begin();
  }
  ll size() {
    if (flag) {
      sort(d.begin(), d.end());
      d.erase(unique(d.begin(), d.end()), d.end());
      flag = false;
    }
    return (ll)d.size();
  }
};

/**** Union Find ****/

class UnionFind {
  vector<ll> par, rank; // par > 0: number, par < 0: -par
public:
  void init(ll n) {
    par.resize(n, 1); rank.resize(n, 0);
  }
  ll getSize(ll x) {
    return par[find(x)];
  }
  ll find(ll x) {
    if (par[x] > 0) return x;
    return -(par[x] = -find(-par[x]));
  }
  void merge(ll x, ll y) {
    x = find(x);
    y = find(y);
    if (x == y) return;
    if (rank[x] < rank[y]) {
      par[y] += par[x];
      par[x] = -y;
    } else {
      par[x] += par[y];
      par[y] = -x;
      if (rank[x] == rank[y]) rank[x]++;
    }
  }
  bool isSame(ll x, ll y) {
    return find(x) == find(y);
  }
};

template <typename T>
struct UnionFindT {
  vector<ll> par;
  vector<ll> rank;
  vector<T> diff_weight;

  UnionFindT(ll n = 1, T SUM_UNITY = 0) {
    init(n, SUM_UNITY);
  }

  void init(ll n = 1, T SUM_UNITY = 0) {
    par.resize(n); rank.resize(n); diff_weight.resize(n);
    for (ll i = 0; i < n; ++i) par[i] = i, rank[i] = 0, diff_weight[i] = SUM_UNITY;
  }

  ll find(ll x) {
    if (par[x] == x) {
      return x;
    }
    else {
      ll r = find(par[x]);
        diff_weight[x] += diff_weight[par[x]];
        return par[x] = r;
    }
  }

  T weight(ll x) {
    find(x);
    return diff_weight[x];
  }

  bool isSame(ll x, ll y) {
    return find(x) == find(y);
  }

  bool merge(ll x, ll y, T w) {
    w += weight(x); w -= weight(y);
    x = find(x); y = find(y);
    if (x == y) return false;
    if (rank[x] < rank[y]) swap(x, y), w = -w;
    if (rank[x] == rank[y]) ++rank[x];
    par[y] = x;
    diff_weight[y] = w;
    return true;
  }

  T diff(ll x, ll y) {
    return weight(y) - weight(x);
  }
};

class PersistentUnionFind {
  vector<ll> rank, fin, par;
  ll index;
public:
  void init(ll n) {
    index = 0;
    par.resize(n); rank.resize(n, 1); fin.resize(n, 0);
    for (ll i = 0; i < n; i++) par[i] = i;
  }
  ll find(ll x, ll t) {
    if (t >= fin[x] && par[x] != x) return find(par[x], t);
    return x;
  }
  void merge(ll x, ll y) {
    x = find(x, index);
    y = find(y, index);
    index++;
    if (x == y) return;
    if (rank[x] < rank[y]) par[x] = y, fin[x] = index;
    else {
      par[y] = x, fin[y] = index;
      if (rank[x] == rank[y]) rank[x]++;
    }
  }
  bool isSame(ll x, ll y, ll t) { return find(x, t) == find(y, t); }
};

/**** Segment Tree ****/

template <typename T>
class SegmentTree {
  ll n;
  vector<T> node;
  function<T(T, T)> fun, fun2;
  bool customChange;
  T outValue, initValue;
public:
  void init(ll num, function<T(T, T)> resultFunction, T init, T out, function<T(T, T)> changeFunction = NULL) {
    // changeFunction: (input, beforevalue) => newvalue
    fun = resultFunction;
    fun2 = changeFunction;
    customChange = changeFunction != NULL;
    n = 1;
    while (n < num) n *= 2;
    node.resize(2 * n - 1, init);
    outValue = out;
    initValue = init;
  }
  void valueChange(ll num, T value) {
    num += n-1;
    if (customChange) node[num] = fun2(value, node[num]);
    else node[num] = value;
    while (num > 0) num = (num - 1) / 2, node[num] = fun(node[num * 2 + 1], node[num * 2 + 2]);
  }
  T rangeQuery(ll a, ll b, ll l = 0, ll r = -1, ll k = 0) { // [a, b)
    if (r == -1) r = n;
    if (a <= l && r <= b) return node[k];
    if (b <= l || r <= a) return outValue;
    ll mid = (l + r) / 2;
    return fun(rangeQuery(a, b, l, mid, 2*k+1), rangeQuery(a, b, mid, r, 2*k+2));
  }
};

template <typename T>
class LazySegmentTree {
  ll n;
  vector<T> node;
  vector<T> lazyNode;
  function<T(T, T)> fun, fun2;
  function<T(T, ll)> fun3;
  T outValue, initValue;
  T substitution(T a, T b) { return a; }
  void eval(ll k, ll l, ll r) {
    if (lazyNode[k] == 0) return;
    node[k] = fun2(fun3(lazyNode[k], r - l), node[k]);
    if (r - l > 1) {
      lazyNode[2 * k + 1] = fun2(lazyNode[k], lazyNode[2 * k + 1]);
      lazyNode[2 * k + 2] = fun2(lazyNode[k], lazyNode[2 * k + 2]);
    }
    lazyNode[k] = initValue;
  }
public:
  void init(ll num, function<T(T, T)> resultFunction, function<T(T, T)> changeFunction, function<T(T, ll)> lazyFunction, T init, T out) {
    // changeFunction: (input, beforevalue) => newvalue
    // lazyFunction: (lazyNode, diff) => newvalue
    fun = resultFunction;
    fun2 = changeFunction;
    fun3 = lazyFunction;
    n = 1;
    while (n < num) n *= 2;
    node.resize(2 * n - 1, init);
    lazyNode.resize(2 * n - 1, init);
    outValue = out;
    initValue = init;
  }
  void rangeChange(ll a, ll b, T value, ll l = 0, ll r = -1, ll k = 0) {
    if (r == -1) r = n;
    eval(k, l, r);
    if (b <= l || r <= a) return;
    if (a <= l && r <= b) {
      lazyNode[k] = fun2(value, lazyNode[k]);
      eval(k, l, r);
    } else {
      ll mid = (l + r) / 2;
      rangeChange(a, b, value, l, mid, 2*k+1);
      rangeChange(a, b, value, mid, r, 2*k+2);
      node[k] = fun(node[2*k+1], node[2*k+2]);
    }
  }
  T rangeQuery(ll a, ll b, ll l = 0, ll r = -1, ll k = 0) { // [a, b)
    if (r == -1) r = n;
    if (b <= l || r <= a) return outValue;
    eval(k, l, r);
    if (a <= l && r <= b) return node[k];
    ll mid = (l + r) / 2;
    return fun(rangeQuery(a, b, l, mid, 2*k+1), rangeQuery(a, b, mid, r, 2*k+2));
  }
};

/**** Network Flow ****/

class MaxFlow {
public:
  struct edge { ll to, cap, rev; };

  vector<edge> G[MAX_FLOW_MAX_V];
  bool used[MAX_FLOW_MAX_V];
  ll level[MAX_FLOW_MAX_V];
  ll iter[MAX_FLOW_MAX_V];
  
  void init() {
    for (ll i = 0; i < MAX_FLOW_MAX_V; i++) {
      G[i].clear();
    }
  }
  void add_edge(ll from, ll to, ll cap) {
    G[from].push_back((edge){to, cap, (ll)G[to].size()});
    G[to].push_back((edge){from, 0, (ll)G[from].size() - 1});
  }
  void add_undirected_edge(ll e1, ll e2, ll cap) {
    G[e1].push_back((edge){e2, cap, (ll)G[e2].size()});
    G[e2].push_back((edge){e1, cap, (ll)G[e1].size() - 1});
  }
  ll dfs(ll v, ll t, ll f) {
    if (v == t) return f;
    used[v] = true;
    for (ll i = 0; i < (ll)G[v].size(); i++) {
      edge &e = G[v][i];
      if (!used[e.to]&& e.cap > 0) {
        ll d = dfs(e.to, t, min(f, e.cap));
        if (d > 0) {
          e.cap -= d;
          G[e.to][e.rev].cap += d;
          return d;
        }
      }
    }
    return 0;
  }
  ll max_flow(ll s, ll t) {
    ll flow = 0;
    while (1) {
      memset(used, 0, sizeof(used));
      ll f = dfs(s, t, INF);
      if (f == 0) return flow;
      flow += f;
    }
  }
  void bfs(ll s) {
    memset(level, -1, sizeof(level));
    queue<ll> que;
    level[s] = 0;
    que.push(s);
    while (!que.empty()) {
      ll v = que.front(); que.pop();
      for (ll i = 0; i < (ll)G[v].size(); i++) {
        edge &e = G[v][i];
        if (e.cap > 0 && level[e.to] < 0) {
          level[e.to] = level[v] + 1;
          que.push(e.to);
        }
      }
    }
  }
  ll dinic_dfs(ll v, ll t, ll f) {
    if (v == t) return f;
    for (ll &i= iter[v]; i < (ll)G[v].size(); i++) {
      edge &e = G[v][i];
      if (e.cap > 0 && level[v] < level[e.to]) {
        ll d = dinic_dfs(e.to, t, min(f, e.cap));
        if (d > 0) {
          e.cap -= d;
          G[e.to][e.rev].cap += d;
          return d;
        }
      }
    }
    return 0;
  }
  ll dinic(ll s, ll t) {
    ll flow = 0;
    while (1) {
      bfs(s);
      if (level[t] < 0) return flow;
      memset(iter, 0, sizeof(iter));
      ll f;
      while ((f = dinic_dfs(s, t, INF)) > 0) {
        flow += f;
      }
    }
  }
};

/**** bipartite matching ****/

class BipartiteMatching {
public:
  ll V;
  vector<ll> G[BIPARTITE_MATCHING_MAX_V];
  ll match[BIPARTITE_MATCHING_MAX_V];
  bool used[BIPARTITE_MATCHING_MAX_V];
  
  BipartiteMatching(ll v) {
    V = v;
  }
  void init(ll v) {
    V = v;
    for (ll i = 0; i < BIPARTITE_MATCHING_MAX_V; i++) {
      G[i].clear();
    }
  }
  void add_edge(ll u, ll v) {
    G[u].push_back(v);
    G[v].push_back(u);
  }
  bool dfs(ll v) {
    used[v] = true;
    for (ll i = 0; i < (ll)G[v].size(); i++) {
      ll u = G[v][i], w = match[u];
      if (w < 0 || !used[w] && dfs(w)) {
        match[v] = u;
        match[u] = v;
        return true;
      }
    }
    return false;
  }
  ll max_matching() {
    ll res = 0;
    memset(match, -1, sizeof(match));
    for (ll v = 0; v < V;v++) {
      if (match[v] < 0) {
        memset(used, 0, sizeof(used));
        if (dfs(v)) {
          res++;
        }
      }
    }
    return res;
  }
};

class MinCostFlow {
public:
  struct edge { ll to, cap, cost, rev; };

  ll V;
  vector<edge> G[MIN_COST_FLOW_MAX_V];
  ll dist[MIN_COST_FLOW_MAX_V];
  ll prevv[MIN_COST_FLOW_MAX_V];
  ll preve[MIN_COST_FLOW_MAX_V];
  ll h[MIN_COST_FLOW_MAX_V];

  MinCostFlow(ll v) {
    V = v;
  }
  void init() {
    for (ll i = 0; i < MAX_FLOW_MAX_V; i++) {
      G[i].clear();
    }
  }
  void add_edge(ll from, ll to, ll cap, ll cost) {
    G[from].push_back((edge){to, cap, cost, (ll)G[to].size()});
    G[to].push_back((edge){from, 0, -cost, (ll)G[from].size() - 1});
  }
  void add_undirected_edge(ll e1, ll e2, ll cap, ll cost) {
    add_edge(e1, e2, cap, cost);
    add_edge(e2, e1, cap, cost);
  }
  ll min_cost_flow(ll s, ll t, ll f) { // minas
    ll res = 0;
    while (f > 0) {
      fill(dist, dist + V, INF);
      dist[s] = 0;
      bool update = true;
      while (update) {
        update = false;
        for (ll v = 0; v < V; v++) {
          if (dist[v] == INF) continue;
          for (ll i = 0; i < (ll)G[v].size(); i++) {
            edge &e = G[v][i];
            if (e.cap > 0 && dist[e.to] > dist[v] + e.cost) {
              dist[e.to] = dist[v] + e.cost;
              prevv[e.to] = v;
              preve[e.to] = i;
              update = true;
            }
          }
        }
      }
      if (dist[t] == INF) {
        return -1;
      }
      ll d = f;
      for (ll v = t; v != s; v = prevv[v]) {
        d = min(d, G[prevv[v]][preve[v]].cap);
      }
      f -= d;
      res += d * dist[t];
      for (ll v = t; v != s; v = prevv[v]) {
        edge &e = G[prevv[v]][preve[v]];
        e.cap -= d;
        G[v][e.rev].cap += d;
      }
    }
    return res;
  }
  ll min_cost_flow_dijkstra(ll s, ll t, ll f) {
    ll res = 0;
    fill(h, h + V, 0);
    while (f > 0) {
      priority_queue<P, vector<P>, greater<P> > que;
      fill(dist, dist + V, 0);
      dist[s] = 0;
      que.push(P(0, s));
      while (!que.empty()) {
        P p = que.top(); que.pop();
        int v = p.second;
        if (dist[v] < p.first) continue;
        for (int i = 0; i < G[v].size(); i++) {
          edge &e = G[v][i];
          if (e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
            dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
            prevv[e.to] = v;
            preve[e.to] = i;
            que.push(P(dist[e.to], e.to));
          }
        }
      }
      if (dist[t] == INF) {
        return -1;
      }
      for (int v = 0; v < V; v++) h[v] += dist[v];
      int d = f;
      for (int v = t; v != s; v = prevv[v]) {
        d = tmin<ll>(d, G[prevv[v]][preve[v]].cap);
      }
      f -= d;
      res += d * h[t];
      for (int v = t; v != s; v = prevv[v]) {
        edge &e = G[prevv[v]][preve[v]];
        e.cap -= d;
        G[v][e.rev].cap += d;
      }
      return res;
    }
    return 0;
  }
};

/**** LIS ****/
ll lis(ll* a, ll n, ll* dp) {
  fill(dp, dp + n, INF);
  for (ll i = 0; i < n; i++) *lower_bound(dp, dp + n, a[i]) = a[i];
  return (ll)(lower_bound(dp, dp + n, INF) - dp);
}

/**** Geometry ****/

bool isEqual(double a, double b) { return abs(a - b) < EPS; }
bool isCEqual(C a, C b) { return isEqual(a.cx, a.cy) && isEqual(a.cy, a.cy); }
bool isZero(double a) { return abs(a) < EPS; } // a == 0
bool isUZero(double a) { return a > EPS; } // a > 0
bool isUEZero(double a) { return a > -EPS; } // a >= 0
bool isLZero(double a) { return a < -EPS; } // a < 0
bool isLEZero(double a) { return a < EPS; } // a <= 0
C getUnitVector(C a) { double len = abs(a); return isZero(len) ? C(0.0, 0.0) : a / len; }
double dot(C a, C b) { return a.cx * b.cx + a.cy * b.cy; } // |a||b|cosθ
double det(C a, C b) { return a.cx * b.cy - a.cy * b.cx; } // |a||b|sinθ
bool isLineOrthogonal(C a1, C a2, C b1, C b2) { return isZero(dot(a1 - a2, b1 - b2)); } // a1-a2, b1-b2
bool isLineParallel(C a1, C a2, C b1, C b2) { return isZero(det(a1 - a2, b1 - b2)); } // a1-a2, b1-b2
bool isPointOnLine(C a, C b, C c) { return isZero(det(b - a, c - a)); } // a-b <- c
bool isPointOnLineSegment(C a, C b, C c) { // a-b <- c
  return isZero(det(b - a, c - a)) && isUEZero(dot(b - a, c - a)) && isUEZero(dot(a - b, c - b));
}
// bool isPointOnLineSegment(C a, C b, C c) { return isZero(abs(a-c) + abs(c-b) - abs(a-b)); }
double distanceLineAndPoint(C a, C b, C c) { return abs(det(b-a, c-a)) / abs(b-a); } // a-b <- c
double distanceLineSegmentAndPoint(C a, C b, C c) { // a-b <- c
  if (isLEZero(dot(b-a, c-a))) return abs(c-a);
  if (isLEZero(dot(a-b, c-b))) return abs(c-b);
  return abs(det(b-a, c-a)) / abs(b-a);
}
bool isIntersectedLine(C a1, C a2, C b1, C b2) { // a1-a2, b1-b2
  return !isLineParallel(a1, a2, b1, b2);
}
C intersectionLine(C a1, C a2, C b1, C b2) { // isIntersectedLine-> true
  C a = a2 - a1, b = b2 - b1;
  return a1 + a * det(b, b1 - a1) / det(b, a);
}

/**** NG Words ****/
// cx cy P Q C
// Warning: EPS

/**** main function ****/

double DINF = 1e30;
ll n, m, ans[10];
double x, y, v[10], t[10];
C d[10], fp, fv;

int main() {
  while (scanf("%lld%lld", &n, &m), n) {
    for (ll i = 0; i < n; i++) scanf("%lf%lf%lf", &x, &y, &v[i]), d[i] = C(x, y), ans[i] = 0;
    for (ll i = 0; i < m; i++) {
      scanf("%lf%lf", &x, &y), fp = C(x, y);
      scanf("%lf%lf", &x, &y), fv = C(x, y);
      double mint = DINF;
      for (ll j = 0; j < n; j++) {
        double ax = fp.cx - d[j].cx;
        double ay = fp.cy - d[j].cy;
        double bx = fv.cx;
        double by = fv.cy;
        double A = bx * bx + by * by - v[j] * v[j];
        double B = ax * bx + ay * by;
        double C = ax * ax + ay * ay;
        // At^2 + 2Bt + C = 0
        if (isZero(A)) {
          if (isZero(B)) t[j] = DINF;
          else {
            double temp = C / (2 * B);
            if (isLZero(temp)) t[j] = DINF;
            else t[j] = temp, mint = min(mint, temp);
          }
        } else {
          double D = B * B - A * C;
          if (isLZero(D)) t[j] = DINF;
          else if (isZero(D)) {
            double temp = -B / A;
            if (isLZero(temp)) t[j] = DINF;
            else t[j] = temp, mint = min(mint, temp);
          } else {
            double t2 = sqrt(D);
            double temp = (-B - t2) / A;
            if (isLZero(temp)) temp = (-B + t2) / A;
            if (isLZero(temp)) t[j] = DINF;
            else t[j] = temp, mint = min(mint, temp);
          }
        }
      }
      for (ll j = 0; j < n; j++) {
        if (isZero(t[j] - DINF)) continue;
        d[j] = (fp + fv * t[j] - d[j]) * mint / t[j] + d[j];
        if (isZero(t[j] - mint)) ans[j]++;
      }
    }
    for (ll i = 0; i < n; i++) printf("%lld%c", ans[i], i==n-1 ? '\n' : ' ');
  }
}
accuracy: 1
time_ms: 40
memory_kb: 2584
final_rank: 3

code_snippet: #include <iostream>
#include <complex>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
const double EPS = 1e-10;
const double INF = 1e12;
#define EQ(n,m) (abs((n)-(m)) < EPS)
#define X real()
#define Y imag()
typedef complex<double> P;
typedef vector<P> VP;

int main(){
    while(1){
        int n,m;
        cin >> n >> m;
        if(n == 0) break;

        VP dog(n);
        vector<double> v(n);
        for(int i=0; i<n; i++){
            double x,y;
            cin >> x >> y >> v[i];
            dog[i] = P(x, y);
        }

        VP fp(m), dir(m);
        for(int i=0; i<m; i++){
            double xp,yp,xd,yd;
            cin >> xp >> yp >> xd >> yd;
            fp[i] = P(xp, yp);
            dir[i] = P(xd, yd);
        }

        vector<int> ans(n, 0);
        for(int i=0; i<m; i++){
            //座標変換(フリスビー位置を原点、投げる方向をx軸方向に)
            P bpos = fp[i];
            P bdir = dir[i]/abs(dir[i]);
            for(int j=0; j<n; j++){
                dog[j] -= bpos;
                dog[j] /= bdir;
            }
            for(int j=0; j<m; j++){
                fp[j] -= bpos;
                fp[j] /= bdir;
                dir[j] /= bdir;
            }

            vector<bool> run(n, false);
            VP rdir(n);
            double tmin = INF;
            int minidx = -1;
            //2次方程式を解く
            for(int j=0; j<n; j++){
                double a,b,c;
                a = 1 -(v[j]*v[j] /norm(dir[i]));
                b = -2 *dog[j].X;
                c = norm(dog[j]);
                double sol = INF;
                if(abs(a) < EPS){
                    if(abs(b) > EPS && -c/b > 0){
                        sol = -c/b;
                    }
                }else{
                    double d = b*b -4*a*c;
                    if(abs(d) < EPS) d = 0;
                    if(d >= 0){
                        double tmp[2] = {(-b+sqrt(d))/(2*a), (-b-sqrt(d))/(2*a)};
                        if(tmp[0] > 0) sol = min(sol, tmp[0]);
                        if(tmp[1] > 0) sol = min(sol, tmp[1]);
                    }
                }

                if(sol == INF) continue;
                run[j] = true;
                rdir[j] = P(sol, 0) -dog[j];
                rdir[j] *= v[j] /abs(rdir[j]);
                double time = sol/dir[i].X;
                if(time < tmin){
                    tmin = time;
                    minidx = j;
                }
            }
            for(int j=0; j<n; j++){
                if(run[j]){
                    dog[j] += tmin *rdir[j];
                }
            }
            if(minidx != -1){
                ans[minidx]++;
            }
        }

        for(int i=0; i<n-1; i++){
            cout << ans[i] << " ";
        }
        cout << ans[n-1] << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 880
memory_kb: 3112
final_rank: 18

code_snippet: #include <bits/stdc++.h>
#define double long double
using namespace std;
typedef complex<double> P;
const int INF = 1e9;

double calc_time(P s,P t,P dog,double v){
  dog -= s;
  double a = abs(t*t)-v*v;
  double b = -2*(t.real()*dog.real()+t.imag()*dog.imag());
  double c = abs(dog*dog);

  if(a<0) a*=-1,b*=-1,c*=-1;
  double d = b*b-4*a*c;
  if(d < 0)return -1;
  
  if(-b-sqrt(d)>= 0) return (-b-sqrt(d))/(2*a);
  if(-b+sqrt(d)>= 0) return (-b+sqrt(d))/(2*a);
  return -1;
}

P Go(P s,P t,P dog,double v,double x,double T){
  t*=T;
  dog -= s;
  P res = (t - dog)/abs(t - dog);
  return (res*v*x)+dog+s;
}

int main(){
  
  while(1){
    int n,m;
    cin>>n>>m;
    if(!n&&!m)break;

    P dog[11];
    double v[11];
    for(int i=0;i<n;i++){
      double x,y;
      cin>>x>>y>>v[i];
      dog[i] = P(x,y);
    }

    int ans[11]={};
    while(m--){
      P s,t;
      double x,y;
      cin>>x>>y; s = P(x,y);
      cin>>x>>y; t = P(x,y);

      double mnt = INF ,time[11] = {};
      for(int i=0;i<n;i++){
	time[i] = calc_time(s,t,dog[i],v[i]);
	if(time[i]>=0)mnt = min(mnt,time[i]);
      }
      for(int i=0;i<n;i++){
	if(time[i]>0)dog[i] = Go(s,t,dog[i],v[i],mnt,time[i]);
	ans[i] += time[i] == mnt;
      }


    }

    for(int i=0;i<n;i++){if(i)cout<<" ";cout<<ans[i];}
    cout<<endl;
  }
  return 0;
}
accuracy: 1
time_ms: 180
memory_kb: 3228
final_rank: 11

code_snippet: #include<bits/stdc++.h>
using namespace std;
const double eps=1e-8;
#define MAX_N 10
#define MAX_M 1000

double Sqrt(double x){
  if(x<0)return 0;
  return sqrt(x);
}

int n,m;
double dx[MAX_N],dy[MAX_N],dv[MAX_N];
double fpx[MAX_M],fpy[MAX_M],fvx[MAX_M],fvy[MAX_M];

double ddx[MAX_N],ddy[MAX_N];
double gett[MAX_N];

double calcdir(int id){
  double res=1e20;
  
  for(int i=0;i<n;i++){
    ddx[i]=ddy[i]=0;
    gett[i]=1e20;
    
    double cx = fpx[id]-dx[i];
    double cy = fpy[id]-dy[i];
    double A=fvx[id]*fvx[id]+fvy[id]*fvy[id]-dv[i]*dv[i];
    double B=2.0*(fvx[id]*cx+fvy[id]*cy);
    double C=cx*cx+cy*cy;
    if( B*B-4.0*A*C < -eps )continue;
    double t0 = ( -B + Sqrt(B*B-4.0*A*C) ) / ( 2.0*A );
    double t1 = ( -B - Sqrt(B*B-4.0*A*C) ) / ( 2.0*A );
    double mini=1e20;
    if( -eps < t0 )mini=min(mini,t0);
    if( -eps < t1 )mini=min(mini,t1);
    if(mini==1e20)continue;
    res=min(res,mini);
    gett[i]=mini;
    
    double nfx = fpx[id]+fvx[id]*mini;
    double nfy = fpy[id]+fvy[id]*mini;
    ddx[i] = nfx - dx[i];
    ddy[i] = nfy - dy[i];

    double len= Sqrt(ddx[i]*ddx[i] + ddy[i]*ddy[i]);
    if(len>eps){
      ddx[i]/=len;
      ddy[i]/=len;
    }

  }
  return res;
}

int ans[MAX_N];

void solve(){
  memset( ans , 0 , sizeof(ans) );
  for(int i=0;i<m;i++){
    double t=calcdir(i);
    for(int j=0;j<n;j++){
      if( gett[j] == t )ans[j]++;
      dx[j]=dx[j]+t*ddx[j]*dv[j];
      dy[j]=dy[j]+t*ddy[j]*dv[j];
    }
  }

  for(int i=0;i<n;i++){
    if(i)cout<<' ';
    cout<<ans[i];
  }
  cout<<endl;
}

int main(){
  while(1){
    cin>>n>>m;
    if(n==0&&m==0)break;
    for(int i=0;i<n;i++){
      cin>>dx[i]>>dy[i]>>dv[i];
    }
    for(int i=0;i<m;i++){
      cin>>fpx[i]>>fpy[i]>>fvx[i]>>fvy[i];
    }
    solve();
  }
  return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 3228
final_rank: 9

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld = long double;
using Point = complex<ld>;
const ld eps = 1e-9;

vector<ld>quad_equa(ld a, ld b, ld c) {
	ld root = b*b - 4 * a*c;
	if (abs(root) < eps) {
		ld ans = -b / (2 * a);
		return vector<ld>(2, ans);
	}
	else if (root > 0) {
		ld ans = -b / (2 * a);
		vector<ld>anss(2);
		anss[0] = ans + sqrt(root) / (2 * a);
		anss[1] = ans - sqrt(root) / (2 * a);
		if (anss[0] > anss[1])swap(anss[0], anss[1]);
		return anss;
	}
	else {
		return vector<ld>();
	}
}

pair<ld, Point> getway(Point dp,const ld dv, Point fp, Point fv) {
	fp -= dp;
	auto ts= quad_equa(norm(fv)-dv*dv, 2 * fv.real()*fp.real() + 2 * fv.imag()*fp.imag(), norm(fp));
	if (ts.empty()) {
		return make_pair(1e18, Point(0.l, 0.l));
	}
	else {
		ld t;
		if (ts[0] < -eps) {
			if (ts.size()>1) {

				t = ts[1];
			}
			else {
				t = ts[0];
			}
		}
		else t = ts[0];
		if (t < -eps)return make_pair(1e18, Point(0.l, 0.l));
		Point catp = fp + fv*t;
		return make_pair(t, catp / ld(t));
	}
}

int main() {
	while (1) {
		int N; cin >> N;
		int M; cin >> M;
		if (!N)break;
		vector<Point>dps;
		vector<ld>dvs;
		vector<int>nums(N);
		for (int i = 0; i < N; ++i) {
			ld dx, dy, v; cin >> dx >> dy >> v;
			dps.push_back(Point(dx, dy));
			dvs.push_back(v);
		}
		for (int i = 0; i < M; ++i) {
			vector<pair<ld, Point>>ways(N);
			ld fpx, fpy, fvx, fvy; cin >> fpx >> fpy >> fvx >> fvy;
			Point fp(fpx, fpy);
			Point fv(fvx, fvy);
			ld mint = 1e19;
			int minid = -1;
			for (int j = 0; j < N; ++j) {
				ways[j] = getway(dps[j], dvs[j], fp, fv);
				if (mint > ways[j].first) {
					mint = ways[j].first;
					minid = j;
				}
			}
			nums[minid]++;
			for (int j = 0; j < N; ++j) {
				dps[j] += ways[j].second*mint;
			}
		}
		for (int i = 0; i < N; ++i) {
			cout << nums[i];
			if (i == N - 1)cout << endl;
			else cout << " ";
		}
	}
	
	return 0;
}
accuracy: 1
time_ms: 170
memory_kb: 3152
final_rank: 10

code_snippet: #include<iostream>
#include<vector>
#include<algorithm>
#include<utility>
#include<complex>

using namespace std;




typedef complex<double> P;

const double eps = 1e-8;

int calc(double a, double b, double c,pair<double,double>& ans){
	//cout << a <<" "<< b <<" "<< c << endl;
	double rt;
	if ((rt=b*b - 4 * a*c) < 0)return 0;
	rt = sqrt(rt);
	ans.first = (-b - rt) / (2 * a);
	ans.second = (-b + rt) / (2 * a);
	if (ans.first < 0 && ans.second < 0)return 0;
	else if (ans.first < 0){
		swap(ans.first, ans.second);
		return 1;
	}
	else if (ans.second < 0)return 1;
	return 2;

}

struct Dog{
	P pos;
	P v;
	double max_v;
	int cnt;
	Dog(double x,double y,double s){
		pos.real(x); pos.imag(y); max_v = s; cnt = 0;;
	}
};
const double INF = 1e9;
int main(){
	int N, M;
	double x, y, v;
	while (true){
		cin >> N >> M;
		if (N == 0 && M == 0)return 0;

		vector<Dog> dog;
		for (int i = 0; i < N; i++){
			cin >> x >> y >> v;
			dog.push_back(Dog(x, y, v));
		}
		for (int i = 0; i < M; i++){
			cin >> x >> y;
			P FP(x, y);
			cin >> x >> y;
			P FU(x, y);
			double res = INF;
			int index = -1;
			for (int j = 0; j < N; j++){
				pair<double, double> T;
				int num = calc(FU.real()*FU.real() + FU.imag()*FU.imag() - dog[j].max_v*dog[j].max_v,
					2*(FP.real() - dog[j].pos.real())*FU.real() + 2*(FP.imag() - dog[j].pos.imag())*FU.imag(),
					(FP.real() - dog[j].pos.real())*(FP.real() - dog[j].pos.real()) + (FP.imag() - dog[j].pos.imag())*(FP.imag() - dog[j].pos.imag()), T);
		//		cout << T.first << " " << T.second << endl;
				if (num == 2){
					double t = min(T.first, T.second);
					if (t < eps)dog[j].v.real(0), dog[j].v.imag(0);
					dog[j].v = (FP - dog[j].pos) / t + FU;
					if (t < res){
						res = t;
						index = j;
					}
				}
				else  if (num == 1){
					double t = T.first;
					if (t < eps)dog[j].v.real(0), dog[j].v.imag(0);
					dog[j].v = (FP - dog[j].pos) / t + FU;
					if (t < res){
						res = t;
						index = j;
					}
				}
				else{
					dog[j].v.real(0), dog[j].v.imag(0);
				}
		//		cout << res << endl;
			}
			dog[index].cnt++;
			for (int j = 0; j < N; j++){
				dog[j].pos = dog[j].pos + dog[j].v*res;
			}
		}

		for (int i = 0; i < N-1; i++){
			cout << dog[i].cnt << " ";
		}
		cout << dog[N - 1].cnt << endl;

	}



	return(0);
}
accuracy: 1
time_ms: 120
memory_kb: 1248
final_rank: 2

code_snippet: #include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
double dx[11];
double dy[11];
double dv[11];
int ret[11];
double eps=1e-7;
double fx[1100];
double fy[1100];
double vx[1100];
double vy[1100];
double tx[11];
double ty[11];
double ABS(double a){return max(a,-a);}
int main(){
	int a,b;
	while(scanf("%d%d",&a,&b),a){
		for(int i=0;i<a;i++){
			scanf("%lf%lf%lf",dx+i,dy+i,dv+i);
		}
		for(int i=0;i<a;i++)ret[i]=0;
		for(int i=0;i<b;i++){
			scanf("%lf%lf%lf%lf",fx+i,fy+i,vx+i,vy+i);
		}
		for(int i=0;i<b;i++){
			double val=999999999;
			int at=-1;
			for(int j=0;j<a;j++){
				if((dx[j]-fx[i])*(dx[j]-fx[i])+(dy[j]-fy[i])*(dy[j]-fy[i])<eps)at=j;
			}
			if(~at){
				ret[at]++;continue;
			}
			for(int j=0;j<a;j++)tx[j]=ty[j]=0;
			for(int j=0;j<a;j++){
				double A=vx[i]*vx[i]+vy[i]*vy[i]-dv[j]*dv[j];
				double B=2.0*((fx[i]-dx[j])*vx[i]+(fy[i]-dy[j])*vy[i]);
				double C=(fx[i]-dx[j])*(fx[i]-dx[j])+(fy[i]-dy[j])*(fy[i]-dy[j]);
				double t;
				if(ABS(A)<eps){
					if(ABS(B)<eps)continue;
					t=-C/B;
				}else if(B*B-A*C*4>-eps){
					t=(-B-sqrt(max(0.0,B*B-A*C*4)))/A/2;
					if(t<0)t=(-B+sqrt(max(0.0,B*B-A*C*4)))/A/2;
				}else continue;
				if(t<0)continue;
				if(val>t){
					val=t;at=j;
				}
				double sx=fx[i]+vx[i]*t;
				double sy=fy[i]+vy[i]*t;
				tx[j]=(sx-dx[j])/t;
				ty[j]=(sy-dy[j])/t;
			}
			ret[at]++;
			for(int j=0;j<a;j++){
				dx[j]+=val*tx[j];
				dy[j]+=val*ty[j];
			}
		}
		for(int i=0;i<a;i++){
			if(i)printf(" ");
			printf("%d",ret[i]);
		}
		printf("\n");
	}
}
accuracy: 1
time_ms: 60
memory_kb: 1108
final_rank: 1