// Create your own template by modifying this file!
#include <string>
#include <vector>
#include <climits>
#include <cstring>
#include <map>
#include <queue>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <iostream>
#include <set>
#include <unordered_set>
#include <unordered_map>
#include <cassert>
#include <deque>
#include <stack>
#include <functional>
#define X first
#define Y second
#define MAX(x, a) x = max(x, a)
#define MIN(x, a) x = min(x, a)
#define CASET int ___T; scanf("%d ", &___T); while (___T-- > 0)
#define SZ(X) ((int)(X).size())
#define LEN(X) strlen(X)
#define FOR(i,c) for(auto &i: c)
#define ALL(x) (x).begin(),(x).end()
#define REP(i,n) for(int i=0;i<(n);i++)
#define REP1(i,a,b) for(int i=(a);i<=(b);i++)
#define REPL(i,x) for(int i=0;x[i];i++)
#define PER(i,n) for(int i=(n)-1;i>=0;i--)
#define PER1(i,a,b) for(int i=(a);i>=(b);i--)
#define RI1(x) scanf("%d",&x)
#define RI2(x,y) RI1(x), RI1(y)
#define RI3(x,y...) RI1(x), RI2(y)
#define RI4(x,y...) RI1(x), RI3(y)
#define RI5(x,y...) RI1(x), RI4(y)
#define RI6(x,y...) RI1(x), RI5(y)
#define GET_MACRO(_1, _2, _3, _4, _5, _6, NAME, ...) NAME
#define RI(argv...) GET_MACRO(argv, RI6, RI5, RI4, RI3, RI2, RI1)(argv)
#define DRI(argv...) int argv;RI(argv)
#define RS(x) scanf("%s",x)
#define PI(x) printf("%d\n",x)
#define PIS(x) printf("%d ",x)
#define DRL(x) LL x; RL(x)
#ifdef ONLINE_JUDGE
    #define PL(x) printf("%I64d\n",x)
    #define RL(x) scanf("%I64d\n",&x)
#else
    #define PL(x) printf("%lld\n",x)
    #define RL(x) scanf("%lld\n",&x)
#endif
#define MP make_pair
#define PB push_back
#define EB emplace_back
#define BG begin()
#define ED end()
#define PQ priority_queue
#define MS0(x) memset(x,0,sizeof(x))
#define MS1(x) memset(x,-1,sizeof(x))
#define SEP(x) ((x)?'\n':' ')
#define DRA(A, N) VI A(N); REP(i, N) RI(A[i])
using namespace std;
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef long long LL;
const int INF = 1000000000;
template<typename T>
using V = std::vector<T>;

#ifdef DEBUG
     #define debug(args...)            {dbg,args; cerr<<endl;}
#else
    #define debug(args...)              // Just strip off all debug tokens
#endif

struct debugger
{
    template<typename T> debugger& operator , (const T& v)
    {
        cerr<<v<<" ";
        return *this;
    }
} dbg;
#include <vector>
using namespace std;

#define chl(k) (k*2+1)
#define chr(k) (k*2+2)

//template<class Data, class Lazy>
typedef pair<double,double> Data;
typedef double Lazy;

const double pi = acos(-1);
struct SegmentTree {
    // static Data identity;
    int n;
    int size;
    vector<Data> dat;
    vector<Lazy> lazy;

    int real_size;
    SegmentTree(int n_) {
        real_size = n_;
        n = 1;
        size = n_;
        while(n < n_) n *= 2;
        dat = vector<Data>(2*n-1);
        lazy = vector<Lazy>(2*n-1);
        init(0, 0, n);
    }

    void init(int k, int l, int r) {
        if(r - l == 1) {
            if (l < real_size) {
                // TODO set dat[k] of leaf at position l
                dat[k] = MP(1.0, 0.0);
            }
        } else {
            // non-leaf
            int m = (l+r)/2;
            init(chl(k), l, m);
            init(chr(k), m, r);
            dat[k] = combine(dat[chl(k)], dat[chr(k)]);
        }
    }
    void update(int a, int b, const Lazy &d) {
        update(a, b+1, 0, 0, n, d);
    }

    void propagate(int k, int l, int r) {
        // update dat[k] according to lazy value d
        double t = lazy[k];
        double x = dat[k].X * cos(t) + dat[k].Y * sin(t);
        double y = -dat[k].X * sin(t) + dat[k].Y * cos(t);
        dat[k] = MP(x, y);
        if (chr(k) < lazy.size()) {
            lazy[chl(k)] += lazy[k];
            lazy[chr(k)] += lazy[k];
        }
        lazy[k] = 0.0;
    }

    void update(int a, int b, int k, int l, int r, const Lazy &d) {
        // we have to make sure dat[k] is the right value after update
        propagate(k, l, r);
        if (r <= a || b <= l) return;
        if (a <= l && r <= b) {
            lazy[k] = d;
            propagate(k, l, r);
        } else {
            int m = (l+r)/2;
            update(a, b, chl(k), l, m, d);
            update(a, b, chr(k), m, r, d);
            dat[k] = combine(dat[chl(k)], dat[chr(k)]);
        }
    }

    void update(int a, int b, int k, int l, int r, int z) {
        // we have to make sure dat[k] is the right value after update
        propagate(k, l, r);
        if (r <= a || b <= l) return;
        if (a <= l && r <= b) {
            double len = sqrt(dat[k].X*dat[k].X+dat[k].Y*dat[k].Y);
            dat[k].X *= (len+z)/len;
            dat[k].Y *= (len+z)/len;
        } else {
            int m = (l+r)/2;
            update(a, b, chl(k), l, m, z);
            update(a, b, chr(k), m, r, z);
            dat[k] = combine(dat[chl(k)], dat[chr(k)]);
        }
    }

    void update(int a, int z) {
        update(a, a+1, 0, 0, n, z);
    }

    Data query(int a, int b) {
        return query(a, b+1, 0, 0, n);
    }

    Data query(int a, int b, int k, int l, int r) {
        // if [a, b) and [l, r) are disjoint
        if(r <= a || b <= l) return MP(0.0, 0.0);
        propagate(k, l, r);
        // if [l, r) contains [a, b)
        if(a <= l && r <= b) {
            return dat[k];
        } else {
            Data vl = query(a, b, chl(k), l, (l + r) / 2);
            Data vr = query(a, b, chr(k), (l + r) / 2, r);
            return combine(vl, vr);
        }
    }

    Data combine(Data vl, Data vr) {
        return MP(vl.X + vr.X, vl.Y + vr.Y);
    }
};

int main()
{
    DRI(N, M);
    SegmentTree st(N+1);
    REP(i, M) {
        DRI(x);
        if (x == 2) {
            DRI(y, z);
            st.update(y, N, z * 1.0 / 360 * 2 * pi);
        } else {
            DRI(y, z);
            st.update(y, z);
        }
        auto ans = st.query(1, N);
        printf("%.10f %.10f\n", ans.X, ans.Y);
    }
}


#include <bits/stdc++.h>

#define FOR(i,b,e) for(int i=(b); i <= (e); ++i)
#define FORD(i,b,e) for(int i=(b); i >= (e); --i)
#define SIZE(c) (int) (c).size()
#define PB push_back
#define MP make_pair
#define ST first
#define ND second

#define FWD(i,a,b) for (int i=(a); i<(b); ++i)
#define BCK(i,a,b) for (int i=(a); i>(b); --i)

using namespace std;

typedef long long int LLI;
typedef pair < int , int > PII;
typedef pair < LLI , LLI > PLL;

typedef vector < int > VI;
typedef vector < bool > VB;
typedef vector < PII > VP;
typedef vector < LLI > VL;
typedef vector < PLL > VPL;

typedef vector < VI > VVI;
typedef vector < VL > VVL;
typedef vector < VB > VVB;
typedef vector < VP > VVP;

typedef complex<double> comp;

const int MAXD = 1024*1024;
typedef complex<double> val_t;
typedef pair<complex<double>, complex<double>> mod_t;
val_t apply(val_t v, mod_t m){ return m.ST * v + m.ND; }
mod_t bind(mod_t a, mod_t b) { return { b.ST * a.ST, b.ST * a.ND + b.ND }; }  // SPRAWDZIIC OBIE OPCJE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
val_t sum(val_t a, val_t b) { return a + b; }
const val_t VAL_INIT = 0.0; // unit segment initial value
const mod_t MOD_ZERO = { 1.0, 0.0 };
// neutral modifier
struct segment_tree {
int d; val_t V[MAXD]; mod_t M[MAXD];
void init(int n, val_t* initial = NULL){
d = 1; while(d < n) d *= 2;
if(initial) FWD(i,0,n) V[d+i] = initial[i]; else n = 0;
FWD(i,n,d) V[d+i] = VAL_INIT;
BCK(i,d-1,0) V[i] = sum(V[2*i], V[2*i+1]);
FWD(i,1,2*d) M[i] = MOD_ZERO;
}
void modify(int x, int y, mod_t m){ _modify(1,0,d,x,y,m); } // applies m on [x, y)
val_t query(int x, int y){ return _query(1,0,d,x,y); }
// gets val_t of [x, y)
void _bind(int u, mod_t m){ M[u] = bind(M[u], m); }
void _push(int u){
V[u] = apply(V[u], M[u]);
if(u<d) _bind(2*u, M[u]), _bind(2*u+1, M[u]);
M[u] = MOD_ZERO;
}
void _modify(int u, int a, int b, int x, int y, mod_t m){
_push(u);
if(x <= a && b <= y){
_bind(u, m); _push(u);
return;
}
if(x<(a+b)/2) _modify(2*u, a, (a+b)/2, x, y, m); else _push(2*u);
if((a+b)/2<y) _modify(2*u+1, (a+b)/2, b, x, y, m); else _push(2*u+1);
V[u] = sum(V[2*u], V[2*u+1]);
}
val_t _query(int u, int a, int b, int x, int y){
_push(u);
if(x <= a && b <= y) return V[u];
if(y <= (a+b)/2) return _query(2*u, a, (a+b)/2, x, y);
if((a+b)/2 <= x) return _query(2*u+1, (a+b)/2, b, x, y);
return sum(_query(2*u, a, (a+b)/2, x, y), _query(2*u+1, (a+b)/2, b, x, y));
}
};

const double MY_PI = 3.14159265358979323846264;

/*************************************************************************/

int main()
{
    int n, m;
    cin >> n >> m;
    n++;

    segment_tree tree;
    tree.init(n);

    for (int i = 0; i < n; i++) {
      tree.modify(i, i + 1, {1.0, 1. * i});
    }

    while (m--) {
      int type, i, param;
      cin >> type >> i >> param;
      i--;
      if (type == 1) {
        comp vec = tree.query(i + 1, i + 2) - tree.query(i, i + 1);
        vec /= abs(vec);
        vec *= param;
        tree.modify(i + 1, n, { 1.0, vec });
      } else {
        comp rot = polar(1.0, (-1.0 * param / 180 * MY_PI));
        comp prev = tree.query(i, i + 1);
        tree.modify(i + 1, n, { rot, prev - prev * rot });
      }
      comp quer = tree.query(n - 1, n);
      printf("%.10lf %.10lf\n", quer.real(), quer.imag());
    }

    return 0;
}

/*************************************************************************/


#include <bits/stdc++.h>

#define FOR(i,b,e) for(int i=(b); i <= (e); ++i)
#define FORD(i,b,e) for(int i=(b); i >= (e); --i)
#define SIZE(c) (int) (c).size()
#define PB push_back
#define MP make_pair
#define ST first
#define ND second

#define FWD(i,a,b) for (int i=(a); i<(b); ++i)
#define BCK(i,a,b) for (int i=(a); i>(b); --i)

using namespace std;

typedef long long int LLI;
typedef pair < int , int > PII;
typedef pair < LLI , LLI > PLL;

typedef vector < int > VI;
typedef vector < bool > VB;
typedef vector < PII > VP;
typedef vector < LLI > VL;
typedef vector < PLL > VPL;

typedef vector < VI > VVI;
typedef vector < VL > VVL;
typedef vector < VB > VVB;
typedef vector < VP > VVP;

typedef complex<double> comp;

const int MAXD = 1024*1024;
typedef complex<double> val_t;
typedef pair<complex<double>, complex<double>> mod_t;
val_t apply(val_t v, mod_t m){ return m.ST * v + m.ND; }
mod_t bind(mod_t a, mod_t b) { return { b.ST * a.ST, b.ST * a.ND + b.ND }; }  // SPRAWDZIIC OBIE OPCJE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
val_t sum(val_t a, val_t b) { return a + b; }
const val_t VAL_INIT = 0.0; // unit segment initial value
const mod_t MOD_ZERO = { 1.0, 0.0 };
// neutral modifier
struct segment_tree {
int d; val_t V[MAXD]; mod_t M[MAXD];
void init(int n, val_t* initial = NULL){
d = 1; while(d < n) d *= 2;
if(initial) FWD(i,0,n) V[d+i] = initial[i]; else n = 0;
FWD(i,n,d) V[d+i] = VAL_INIT;
BCK(i,d-1,0) V[i] = sum(V[2*i], V[2*i+1]);
FWD(i,1,2*d) M[i] = MOD_ZERO;
}
void modify(int x, int y, mod_t m){ _modify(1,0,d,x,y,m); } // applies m on [x, y)
val_t query(int x, int y){ return _query(1,0,d,x,y); }
// gets val_t of [x, y)
void _bind(int u, mod_t m){ M[u] = bind(M[u], m); }
void _push(int u){
V[u] = apply(V[u], M[u]);
if(u<d) _bind(2*u, M[u]), _bind(2*u+1, M[u]);
M[u] = MOD_ZERO;
}
void _modify(int u, int a, int b, int x, int y, mod_t m){
_push(u);
if(x <= a && b <= y){
_bind(u, m); _push(u);
return;
}
if(x<(a+b)/2) _modify(2*u, a, (a+b)/2, x, y, m); else _push(2*u);
if((a+b)/2<y) _modify(2*u+1, (a+b)/2, b, x, y, m); else _push(2*u+1);
V[u] = sum(V[2*u], V[2*u+1]);
}
val_t _query(int u, int a, int b, int x, int y){
_push(u);
if(x <= a && b <= y) return V[u];
if(y <= (a+b)/2) return _query(2*u, a, (a+b)/2, x, y);
if((a+b)/2 <= x) return _query(2*u+1, (a+b)/2, b, x, y);
return sum(_query(2*u, a, (a+b)/2, x, y), _query(2*u+1, (a+b)/2, b, x, y));
}
};

const double MY_PI = 3.14159265358979323846264;

/*************************************************************************/

int main()
{
    ios_base::sync_with_stdio(0);
    cout << fixed << setprecision(10);

    int n, m;
    cin >> n >> m;
    n++;

    segment_tree tree;
    tree.init(n);

    for (int i = 0; i < n; i++) {
      tree.modify(i, i + 1, {1.0, 1. * i});
    }

    while (m--) {
      int type, i, param;
      cin >> type >> i >> param;
      i--;
      if (type == 1) {
        comp vec = tree.query(i + 1, i + 2) - tree.query(i, i + 1);
        vec /= abs(vec);
        vec *= param;
        tree.modify(i + 1, n, { 1.0, vec });
      } else {
        comp rot = polar(1.0, (-1.0 * param / 180 * MY_PI));
        comp prev = tree.query(i, i + 1);
        tree.modify(i + 1, n, { rot, prev - prev * rot });
      }
      comp quer = tree.query(n - 1, n);
      // printf("%.10lf %.10lf\n", quer.real(), quer.imag());
      cout << quer.real() << ' ' << quer.imag() << '\n';
    }

    return 0;
}

/*************************************************************************/


#include <bits/stdc++.h>

#define FOR(i,b,e) for(int i=(b); i <= (e); ++i)
#define FORD(i,b,e) for(int i=(b); i >= (e); --i)
#define SIZE(c) (int) (c).size()
#define PB push_back
#define MP make_pair
#define ST first
#define ND second

#define FWD(i,a,b) for (int i=(a); i<(b); ++i)
#define BCK(i,a,b) for (int i=(a); i>(b); --i)

using namespace std;

typedef long long int LLI;
typedef pair < int , int > PII;
typedef pair < LLI , LLI > PLL;

typedef vector < int > VI;
typedef vector < bool > VB;
typedef vector < PII > VP;
typedef vector < LLI > VL;
typedef vector < PLL > VPL;

typedef vector < VI > VVI;
typedef vector < VL > VVL;
typedef vector < VB > VVB;
typedef vector < VP > VVP;

typedef complex<double> comp;

const int MAXD = 1024*1024;
typedef complex<double> val_t;
typedef pair<complex<double>, complex<double>> mod_t;
val_t apply(val_t v, mod_t m){ return m.ST * v + m.ND; }
mod_t bind(mod_t a, mod_t b) { return { b.ST * a.ST, b.ST * a.ND + b.ND }; }  // SPRAWDZIIC OBIE OPCJE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
val_t sum(val_t a, val_t b) { return a + b; }
const val_t VAL_INIT = 0.0; // unit segment initial value
const mod_t MOD_ZERO = { 1.0, 0.0 };
// neutral modifier
struct segment_tree {
int d; val_t V[MAXD]; mod_t M[MAXD];
void init(int n, val_t* initial = NULL){
d = 1; while(d < n) d *= 2;
if(initial) FWD(i,0,n) V[d+i] = initial[i]; else n = 0;
FWD(i,n,d) V[d+i] = VAL_INIT;
BCK(i,d-1,0) V[i] = sum(V[2*i], V[2*i+1]);
FWD(i,1,2*d) M[i] = MOD_ZERO;
}
void modify(int x, int y, mod_t m){ _modify(1,0,d,x,y,m); } // applies m on [x, y)
val_t query(int x, int y){ return _query(1,0,d,x,y); }
// gets val_t of [x, y)
void _bind(int u, mod_t m){ M[u] = bind(M[u], m); }
void _push(int u){
V[u] = apply(V[u], M[u]);
if(u<d) _bind(2*u, M[u]), _bind(2*u+1, M[u]);
M[u] = MOD_ZERO;
}
void _modify(int u, int a, int b, int x, int y, mod_t m){
_push(u);
if(x <= a && b <= y){
_bind(u, m); _push(u);
return;
}
if(x<(a+b)/2) _modify(2*u, a, (a+b)/2, x, y, m); else _push(2*u);
if((a+b)/2<y) _modify(2*u+1, (a+b)/2, b, x, y, m); else _push(2*u+1);
V[u] = sum(V[2*u], V[2*u+1]);
}
val_t _query(int u, int a, int b, int x, int y){
_push(u);
if(x <= a && b <= y) return V[u];
if(y <= (a+b)/2) return _query(2*u, a, (a+b)/2, x, y);
if((a+b)/2 <= x) return _query(2*u+1, (a+b)/2, b, x, y);
return sum(_query(2*u, a, (a+b)/2, x, y), _query(2*u+1, (a+b)/2, b, x, y));
}
};

const double MY_PI = 3.14159265358979323846264;

/*************************************************************************/

int main()
{
    ios_base::sync_with_stdio(0);

    cout << setprecision(40);

    int n, m;
    cin >> n >> m;
    n++;

    segment_tree tree;
    tree.init(n);

    for (int i = 0; i < n; i++) {
      tree.modify(i, i + 1, {1.0, 1. * i});
    }

    while (m--) {
      int type, i, param;
      cin >> type >> i >> param;
      i--;
      if (type == 1) {
        comp vec = tree.query(i + 1, i + 2) - tree.query(i, i + 1);
        vec /= abs(vec);
        vec *= param;
        tree.modify(i + 1, n, { 1.0, vec });
      } else {
        comp rot = polar(1.0, (-1.0 * param / 180 * MY_PI));
        comp prev = tree.query(i, i + 1);
        tree.modify(i + 1, n, { rot, prev - prev * rot });
      }
      comp quer = tree.query(n - 1, n);
      cout << quer.real() << ' ' << quer.imag() << '\n';
    }

    return 0;
}

/*************************************************************************/


#include <bits/stdc++.h>

#define FOR(i,b,e) for(int i=(b); i <= (e); ++i)
#define FORD(i,b,e) for(int i=(b); i >= (e); --i)
#define SIZE(c) (int) (c).size()
#define PB push_back
#define MP make_pair
#define ST first
#define ND second

#define FWD(i,a,b) for (int i=(a); i<(b); ++i)
#define BCK(i,a,b) for (int i=(a); i>(b); --i)

using namespace std;

typedef long long int LLI;
typedef pair < int , int > PII;
typedef pair < LLI , LLI > PLL;

typedef vector < int > VI;
typedef vector < bool > VB;
typedef vector < PII > VP;
typedef vector < LLI > VL;
typedef vector < PLL > VPL;

typedef vector < VI > VVI;
typedef vector < VL > VVL;
typedef vector < VB > VVB;
typedef vector < VP > VVP;

typedef complex<double> comp;

const int MAXD = 1024*1024;
typedef complex<double> val_t;
typedef pair<complex<double>, complex<double>> mod_t;
val_t apply(val_t v, mod_t m){ return m.ST * v + m.ND; }
mod_t bind(mod_t a, mod_t b) { return { b.ST * a.ST, b.ST * a.ND + b.ND }; }  // SPRAWDZIIC OBIE OPCJE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
val_t sum(val_t a, val_t b) { return a + b; }
const val_t VAL_INIT = 0.0; // unit segment initial value
const mod_t MOD_ZERO = { 1.0, 0.0 };
// neutral modifier
struct segment_tree {
int d; val_t V[MAXD]; mod_t M[MAXD];
void init(int n, val_t* initial = NULL){
d = 1; while(d < n) d *= 2;
if(initial) FWD(i,0,n) V[d+i] = initial[i]; else n = 0;
FWD(i,n,d) V[d+i] = VAL_INIT;
BCK(i,d-1,0) V[i] = sum(V[2*i], V[2*i+1]);
FWD(i,1,2*d) M[i] = MOD_ZERO;
}
void modify(int x, int y, mod_t m){ _modify(1,0,d,x,y,m); } // applies m on [x, y)
val_t query(int x, int y){ return _query(1,0,d,x,y); }
// gets val_t of [x, y)
void _bind(int u, mod_t m){ M[u] = bind(M[u], m); }
void _push(int u){
V[u] = apply(V[u], M[u]);
if(u<d) _bind(2*u, M[u]), _bind(2*u+1, M[u]);
M[u] = MOD_ZERO;
}
void _modify(int u, int a, int b, int x, int y, mod_t m){
_push(u);
if(x <= a && b <= y){
_bind(u, m); _push(u);
return;
}
if(x<(a+b)/2) _modify(2*u, a, (a+b)/2, x, y, m); else _push(2*u);
if((a+b)/2<y) _modify(2*u+1, (a+b)/2, b, x, y, m); else _push(2*u+1);
V[u] = sum(V[2*u], V[2*u+1]);
}
val_t _query(int u, int a, int b, int x, int y){
_push(u);
if(x <= a && b <= y) return V[u];
if(y <= (a+b)/2) return _query(2*u, a, (a+b)/2, x, y);
if((a+b)/2 <= x) return _query(2*u+1, (a+b)/2, b, x, y);
return sum(_query(2*u, a, (a+b)/2, x, y), _query(2*u+1, (a+b)/2, b, x, y));
}
};

const double MY_PI = 3.14159265358979323846264;

/*************************************************************************/

int main()
{
    ios_base::sync_with_stdio(0);
    cout << fixed << setprecision(40);

    int n, m;
    cin >> n >> m;
    n++;

    segment_tree tree;
    tree.init(n);

    for (int i = 0; i < n; i++) {
      tree.modify(i, i + 1, {1.0, 1. * i});
    }

    while (m--) {
      int type, i, param;
      cin >> type >> i >> param;
      i--;
      if (type == 1) {
        comp vec = tree.query(i + 1, i + 2) - tree.query(i, i + 1);
        vec /= abs(vec);
        vec *= param;
        tree.modify(i + 1, n, { 1.0, vec });
      } else {
        comp rot = polar(1.0, (-1.0 * param / 180 * MY_PI));
        comp prev = tree.query(i, i + 1);
        tree.modify(i + 1, n, { rot, prev - prev * rot });
      }
      comp quer = tree.query(n - 1, n);
      // printf("%.10lf %.10lf\n", quer.real(), quer.imag());
      cout << quer.real() << ' ' << quer.imag() << '\n';
    }

    return 0;
}

/*************************************************************************/


#include <bits/stdc++.h>
using namespace std;
#define rep(i, a) for (int i = 0; i < (a); i++)
#define rep2(i, a, b) for (int i = (a); i < (b); i++)
#define repr(i, a) for (int i = (a) - 1; i >= 0; i--)
#define repr2(i, a, b) for (int i = (b) - 1; i >= (a); i--)
template<class T1, class T2> bool chmin(T1 &a, T2 b) { return b < a && (a = b, true); }
template<class T1, class T2> bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }
typedef long long ll;

typedef complex<long double> C;

struct SegmentTree {
	vector<C> dr;
	vector<long double> angle;
	int n;

	SegmentTree(int n) : n(n) {
		dr.resize(n * 2);
		angle.resize(n * 2);
	}

	void update(int k, long double da, long double dl) {
		k += n - 1;
		long double rho = abs(dr[k]) + dl;
		long double theta = angle[k] + da;
		dr[k] = polar(rho, theta);
		angle[k] = theta;
		while (k > 0) {
			k = (k - 1) / 2;
			angle[k] = angle[k * 2 + 1] + angle[k * 2 + 2];
			dr[k] = dr[k * 2 + 1] + dr[k * 2 + 2] * polar(1.0l, angle[k * 2 + 1]);
		}
	}

	C query() {
		return dr[0];
	}
};

const long double pi = acos(-1.0l);

long double toRad(long double deg) {
	return deg / 180.0l * pi;
}

int main() {
	int n, m;
	cin >> n >> m;

	SegmentTree st(303030);
	rep(i, n) st.update(i, 0, 1);

	rep(i, m) {
		int x, y, z;
		scanf("%d %d %d", &x, &y, &z);
		y--;
		if (x == 1) {
			st.update(y, 0, z);
		} else {
			st.update(y, -toRad(z), 0);
		}
		auto ans = st.query();
		printf("%.20f %.20f\n", (double)real(ans), (double)imag(ans));
	}

	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i, a) for (int i = 0; i < (a); i++)
#define rep2(i, a, b) for (int i = (a); i < (b); i++)
#define repr(i, a) for (int i = (a) - 1; i >= 0; i--)
#define repr2(i, a, b) for (int i = (b) - 1; i >= (a); i--)
template<class T1, class T2> bool chmin(T1 &a, T2 b) { return b < a && (a = b, true); }
template<class T1, class T2> bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }
typedef long long ll;

typedef complex<long double> C;
const long double pi = acos(-1.0l);
const int N = 1 << 19;
C dr[N * 2];
long double angle[N * 2];

void update(int k, long double dl, long double da) {
	k += N - 1;
	long double rho = abs(dr[k]) + dl;
	long double theta = angle[k] + da;
	dr[k] = polar(rho, theta);
	angle[k] = theta;
	while (k > 0) {
		k = (k - 1) / 2;
		angle[k] = angle[k * 2 + 1] + angle[k * 2 + 2];
		dr[k] = dr[k * 2 + 1] + dr[k * 2 + 2] * polar(1.0l, angle[k * 2 + 1]);
	}
}

int main() {
	int n, m;
	cin >> n >> m;
	rep(i, n) update(i, 1, 0);

	rep(i, m) {
		int x, y, z;
		scanf("%d %d %d", &x, &y, &z);
		y--;
		if (x == 1) {
			update(y, z, 0);
		} else {
			update(y, 0, -z / 180.0l * pi);
		}
		auto ans = dr[0];
		printf("%.20f %.20f\n", (double)real(ans), (double)imag(ans));
	}

	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i, a) for (int i = 0; i < (a); i++)
#define rep2(i, a, b) for (int i = (a); i < (b); i++)
#define repr(i, a) for (int i = (a) - 1; i >= 0; i--)
#define repr2(i, a, b) for (int i = (b) - 1; i >= (a); i--)
template<class T1, class T2> bool chmin(T1 &a, T2 b) { return b < a && (a = b, true); }
template<class T1, class T2> bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }
typedef long long ll;

typedef complex<long double> C;
const long double pi = acos(-1.0l);
const int N = 1 << 19;
C dr[N * 2];
long double angle[N * 2];

void update(int k, long double dl, long double da) {
	k += N - 1;
	long double rho = abs(dr[k]) + dl;
	long double theta = angle[k] + da;
	dr[k] = polar(rho, theta);
	angle[k] = theta;
	while (k > 0) {
		k = (k - 1) / 2;
		angle[k] = angle[k * 2 + 1] + angle[k * 2 + 2];
		dr[k] = dr[k * 2 + 1] + dr[k * 2 + 2] * polar(1.0l, angle[k * 2 + 1]);
	}
}

int main() {
	int n, m;
	cin >> n >> m;
	rep(i, n) update(i, 1, 0);

	rep(i, m) {
		int x, y, z;
		scanf("%d %d %d", &x, &y, &z);
		y--;
		if (x == 1) {
			update(y, z, 0);
		} else {
			update(y, 0, z / 180.0l * pi);
		}
		auto ans = dr[0];
		printf("%.20f %.20f\n", (double)real(ans), (double)imag(ans));
	}

	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define rep(i, a) for (int i = 0; i < (a); i++)
#define rep2(i, a, b) for (int i = (a); i < (b); i++)
#define repr(i, a) for (int i = (a) - 1; i >= 0; i--)
#define repr2(i, a, b) for (int i = (b) - 1; i >= (a); i--)
template<class T1, class T2> bool chmin(T1 &a, T2 b) { return b < a && (a = b, true); }
template<class T1, class T2> bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }
typedef long long ll;

typedef complex<long double> C;

struct SegmentTree {
	vector<C> dr;
	vector<long double> angle;
	int n;

	SegmentTree(int size) {
		n = 1;
		while (n < size) n *= 2;
		dr.resize(n * 2);
		angle.resize(n * 2);
	}

	void update(int k, long double da, long double dl) {
		k += n - 1;
		long double rho = abs(dr[k]) + dl;
		long double theta = angle[k] + da;
		dr[k] = polar(rho, theta);
		angle[k] = theta;
		while (k > 0) {
			k = (k - 1) / 2;
			angle[k] = angle[k * 2 + 1] + angle[k * 2 + 2];
			dr[k] = dr[k * 2 + 1] + dr[k * 2 + 2] * polar(1.0l, angle[k * 2 + 1]);
		}
	}

	C query() {
		return dr[0];
	}
};

const long double pi = acos(-1.0l);

long double toRad(long double deg) {
	return deg / 180.0l * pi;
}

int main() {
	int n, m;
	cin >> n >> m;

	SegmentTree st(303030);
	rep(i, n) st.update(i, 0, 1);

	rep(i, m) {
		int x, y, z;
		scanf("%d %d %d", &x, &y, &z);
		y--;
		if (x == 1) {
			st.update(y, 0, z);
		} else {
			st.update(y, -toRad(z), 0);
		}
		auto ans = st.query();
		printf("%.20f %.20f\n", (double)real(ans), (double)imag(ans));
	}

	return 0;
}


#include<stdio.h>
#include<math.h>
#define PI 3.14159265358979323846
double Sin(int d){ return sin(d*PI/180); }
double Cos(int d){ return cos(d*PI/180); }
//double getx(int l, int d){ return l*cos(d*M_PI/180); }
//double gety(int l, int d){ return l*sin(d*M_PI/180); }
struct node
{
	int d, a;
	double x, y;
	node *r, *l;
	void init(int s, int e);
	void op1(int s, int e, int X, int L);
	void op2(int s, int e, int i, int f, int A);
} ST[600010];
int C;
int main()
{
	int n, m, i;
	scanf("%d%d", &n, &m);
	ST->init(1, n);
	int t, s, v;
	for(i=1; i<=m; i++)
	{
		scanf("%d%d%d", &t, &s, &v);
		if(t==1) ST->op1(1, n, s, v);
		else ST->op2(1, n, s, n, 360-v);
		printf("%.10f %.10f\n", ST->x, ST->y);
	}
	return 0;
}
void node::init(int s, int e)
{
	if(s==e) { d=1; a=0; x=1; y = 0; }
	else
	{
		l = ST+(++C); r = ST+(++C);
		l->init(s, (s+e)/2);
		r->init((s+e)/2+1, e);
		x = l->x + r->x;
		y = l->y + r->y;
		d = a = 0;
	}
}
void node::op1(int s, int e, int X, int L)
{
	if(s==e)
	{
		d += L;
		x = d*Cos(a);
		y = d*Sin(a);
		return;
	}
	if(X<=(s+e)/2) l->op1(s, (s+e)/2, X, L);
	else r->op1((s+e)/2+1, e, X, L);
	double xx = l->x + r->x, yy = l->y + r->y;
	x = xx*Cos(a) - yy*Sin(a);
	y = xx*Sin(a) + yy*Cos(a);
}
void node::op2(int s, int e, int i, int f, int A)
{
	if(s > f || e < i) return;
	if(i<=s && e<=f)
	{
		(a += A)%=360;
		double xx=x, yy=y;
		x = xx*Cos(A) - yy*Sin(A);
		y = xx*Sin(A) + yy*Cos(A);
		return;
	}
	l->op2(s, (s+e)/2, i, f, A);
	r->op2((s+e)/2+1, e, i, f, A);
	double xx = l->x + r->x, yy = l->y + r->y;
	x = xx*Cos(a) - yy*Sin(a);
	y = xx*Sin(a) + yy*Cos(a);
}


#include<stdio.h>
#include<math.h>
#define PI 3.14159265358979323846
double Sin(int d){ return sin(d*PI/180); }
double Cos(int d){ return cos(d*PI/180); }
//double getx(int l, int d){ return l*cos(d*M_PI/180); }
//double gety(int l, int d){ return l*sin(d*M_PI/180); }
struct node
{
	int d, a;
	double x, y;
	node *r, *l;
	void init(int s, int e);
	void op1(int s, int e, int X, int L);
	void op2(int s, int e, int i, int f, int A);
} ST[600010];
int C;
int main()
{
	int n, m, i;
	scanf("%d%d", &n, &m);
	ST->init(1, n);
	int t, s, v;
	for(i=1; i<=m; i++)
	{
		scanf("%d%d%d", &t, &s, &v);
		if(t==1) ST->op1(1, n, s, v);
		else ST->op2(1, n, s, n, 360-v);
		printf("%.10f %.10f\n", ST->x, ST->y);
	}
	return 0;
}
void node::init(int s, int e)
{
	if(s==e) { d=1; a=0; x=1; y = 0; }
	else
	{
		l = ST+(++C); r = ST+(++C);
		l->init(s, (s+e)/2);
		r->init((s+e)/2+1, e);
		x = l->x + r->x;
		y = l->y + r->y;
		d = a = 0;
	}
}
void node::op1(int s, int e, int X, int L)
{
	if(s==e)
	{
		d += L;
		x = d*Cos(a);
		y = d*Sin(a);
		return;
	}
	if(X<=(s+e)/2) l->op1(s, (s+e)/2, X, L);
	else r->op1((s+e)/2+1, e, X, L);
	double xx = l->x + r->x, yy = l->y + r->y;
	x = xx*Cos(a) - yy*Sin(a);
	y = xx*Sin(a) + yy*Cos(a);
}
void node::op2(int s, int e, int i, int f, int A)
{
	if(s > f || e < i) return;
	if(i<=s && e<=f)
	{
		(a += A)%=360;
		double xx=l->x+r->x, yy=l->y+r->y;
		x = xx*Cos(a) - yy*Sin(a);
		y = xx*Sin(a) + yy*Cos(a);
		return;
	}
	l->op2(s, (s+e)/2, i, f, A);
	r->op2((s+e)/2+1, e, i, f, A);
	double xx = l->x + r->x, yy = l->y + r->y;
	x = xx*Cos(a) - yy*Sin(a);
	y = xx*Sin(a) + yy*Cos(a);
}


#include<stdio.h>
#include<math.h>
#define PI 3.14159265358979323846
double Sin(int d){ return sin(d*PI/180); }
double Cos(int d){ return cos(d*PI/180); }
//double getx(int l, int d){ return l*cos(d*M_PI/180); }
//double gety(int l, int d){ return l*sin(d*M_PI/180); }
struct node
{
	int d, a;
	double x, y;
	node *r, *l;
	void init(int s, int e);
	void op1(int s, int e, int X, int L);
	void op2(int s, int e, int i, int f, int A);
} ST[600010];
int C;
int main()
{
	int n, m, i;
	scanf("%d%d", &n, &m);
	ST->init(1, n);
	int t, s, v;
	for(i=1; i<=m; i++)
	{
		scanf("%d%d%d", &t, &s, &v);
		if(t==1) ST->op1(1, n, s, v);
		else ST->op2(1, n, s, n, 360-v);
		printf("%.10f %.10f\n", ST->x, ST->y);
	}
	return 0;
}
void node::init(int s, int e)
{
	if(s==e) { d=1; a=0; x=1; y = 0; }
	else
	{
		l = ST+(++C); r = ST+(++C);
		l->init(s, (s+e)/2);
		r->init((s+e)/2+1, e);
		x = l->x + r->x;
		y = l->y + r->y;
		d = a = 0;
	}
}
void node::op1(int s, int e, int X, int L)
{
	if(s==e)
	{
		d += L;
		x = d*Cos(a);
		y = d*Sin(a);
		return;
	}
	if(X<=(s+e)/2) l->op1(s, (s+e)/2, X, L);
	else r->op1((s+e)/2+1, e, X, L);
	double xx = l->x + r->x, yy = l->y + r->y;
	x = xx*Cos(a) - yy*Sin(a);
	y = xx*Sin(a) + yy*Cos(a);
}
void node::op2(int s, int e, int i, int f, int A)
{
	if(s > f || e < i) return;
	if(i<=s && e<=f)
	{
		(a += A)%=360;
		double xx=x, yy=y;
		x = xx*Cos(a) - yy*Sin(a);
		y = xx*Sin(a) + yy*Cos(a);
		return;
	}
	l->op2(s, (s+e)/2, i, f, A);
	r->op2((s+e)/2+1, e, i, f, A);
	double xx = l->x + r->x, yy = l->y + r->y;
	x = xx*Cos(a) - yy*Sin(a);
	y = xx*Sin(a) + yy*Cos(a);
}


#include <bits/stdc++.h>

#ifdef _WIN32
#define getchar_unlocked getchar
#endif
#define II (read32())
#define IU (readu32())
#define IL (read64())
#define IUL (readu64())
uint32_t readu32() { int c; while((c = getchar_unlocked()) < '0'); uint32_t n = c & 15U; while((c = getchar_unlocked()) >= '0') n = n * 10 + (c & 15U); return n; } uint64_t readu64() { int c; while((c = getchar_unlocked()) < '0'); uint64_t n = c & 15U; while((c = getchar_unlocked()) >= '0') n = n * 10 + (c & 15U); return n; } int32_t read32() { int c; while((c = getchar_unlocked()) < '-'); bool neg = c == '-'; if(neg) c = getchar_unlocked(); uint32_t n = c & 15U; while((c = getchar_unlocked()) >= '0') n = n * 10 + (c & 15U); return neg ? -(int32_t)n : n; } int64_t read64() { int c; while((c = getchar_unlocked()) < '-'); bool neg = c == '-'; if(neg) c = getchar_unlocked(); uint64_t n = c & 15; while((c = getchar_unlocked()) >= '0') n = n * 10 + (c & 15U); return neg ? -(int64_t)n : n; }
template<typename T, int N> struct mat { T dat[N*N]; struct id_s {}; static const id_s id; mat(): dat{} { } mat(std::initializer_list<T> l) { int i = 0; for(auto&& x: l) dat[i++] = x; for(; i < N*N; i++) dat[i] = 0; } mat(int m): dat{} { for(int i = 0; i < N; i++) (*this)(i,i) = m; } mat(id_s) { for(int i = 0; i < N; i++) for(int j = 0; j < N; j++) dat[N*i + j] = +(i==j); } T& operator()(int i, int j) { return dat[N*i + j]; } const T& operator()(int i, int j) const { return dat[N*i + j]; } mat operator*(const mat& o) { mat r; for(int i = 0; i < N; i++) for(int j = 0; j < N; j++) for(int k = 0; k < N; k++) r(i,j) += (*this)(i,k) * o(k,j); return r; } mat operator+(const mat& o) { mat r; for(int i = 0; i < N*N; i++) r.dat[i] = dat[i] + o.dat[i]; return r; } };
template<typename V, typename Op, bool hasID=false> struct bitsg { V* dat = nullptr; typedef size_t I; size_t size; template<typename It> void init(size_t n, It a, It b) { delete[] dat; size = n; dat = new V[datlen()]; I i = 0; for(; a != b; a++) dat[i++] = *a; if(hasID) { for(; i < n; i++) dat[i++] = V{}; } calcfromelem(); } bitsg() {} template<typename It> bitsg(size_t n, It a, It b) { init(n, a, b); } ~bitsg() { delete[] dat; } size_t datlen() { return 2*size - __builtin_popcount(size); } void calcfromelem() { V* p = dat; for(I n = size; n > 1; n >>= 1) { for(I i = 0; i < n/2; i++) { p[n + i] = Op()(p[2*i], p[2*i+1]); } p += n; } } V sum(I a, I b) const { assert(a >= 0 && b >= a && b <= size); V ra, rb; bool ha = false, hb = false; size_t sz = size; V* dp = dat; while(b > a) { if(a & 1) { if(ha) ra = Op()(ra, dp[a]); else ha = true, ra = dp[a]; a++; } if(b & 1) { if(hb) rb = Op()(dp[b-1], rb); else hb = true, rb = dp[b-1]; b--; } dp += sz; sz >>= 1; a >>= 1; b >>= 1; } if(ha && hb) return Op()(ra, rb); if(ha) return ra; if(hb) return rb; assert(hasID); return V{}; } const V& get(I i) const { assert(i < size); return dat[i]; } void set(I i, V&& v) { assert(i < size); V* cur = &(dat[i] = v); V* p = dat; size_t sz = size; while(i>>1 < sz>>1) { V val; if(i & 1) val = Op()(p[i-1], *cur); else val = Op()(*cur, p[i+1]); p += sz; cur = &(p[i >>= 1] = std::move(val)); sz >>= 1; } } };

typedef mat<double, 3> M;

using namespace std;

M rot(int a) {
    double ra = a * (3.14159265358979323846 / 180);
    double c = cos(ra), s = sin(ra);
    return M{c, -s, 0.,
             s,  c, 0.,
             0.,  0., 1.};
}

M trans(double d) {
    return M{1., 0., d,
             0., 1., 0.,
             0., 0., 1.};
}

struct tim {
    M operator()(M& a, M& b) {return a*b;}
};

int main()
{
    ios_base::sync_with_stdio(0);

    int n=IU, m=IU;

    bitsg<M, tim > b;
     b.size = 2*n;
    b.dat = new M[b.datlen()];

    for(int i=0; i<n; i++)
        b.dat[2*i] = M(M::id),
        b.dat[2*i+1] = trans(1);
    b.calcfromelem();

    while(m--) {
        int x=IU, y=IU-1, z=IU;
        if(x == 1)
            b.set(2*y+1, b.dat[2*y+1] * trans(z));
        else
            b.set(2*y, b.dat[2*y] * rot(-z));

        M t = b.sum(0, 2*n);
        printf("%.12f %.12f\n", t.dat[2], t.dat[5]);
    }

    return 0;
}


#include <bits/stdc++.h>

#ifdef _WIN32
#define getchar_unlocked getchar
#endif
#define II (read32())
#define IU (readu32())
#define IL (read64())
#define IUL (readu64())
uint32_t readu32() { int c; while((c = getchar_unlocked()) < '0'); uint32_t n = c & 15U; while((c = getchar_unlocked()) >= '0') n = n * 10 + (c & 15U); return n; } uint64_t readu64() { int c; while((c = getchar_unlocked()) < '0'); uint64_t n = c & 15U; while((c = getchar_unlocked()) >= '0') n = n * 10 + (c & 15U); return n; } int32_t read32() { int c; while((c = getchar_unlocked()) < '-'); bool neg = c == '-'; if(neg) c = getchar_unlocked(); uint32_t n = c & 15U; while((c = getchar_unlocked()) >= '0') n = n * 10 + (c & 15U); return neg ? -(int32_t)n : n; } int64_t read64() { int c; while((c = getchar_unlocked()) < '-'); bool neg = c == '-'; if(neg) c = getchar_unlocked(); uint64_t n = c & 15; while((c = getchar_unlocked()) >= '0') n = n * 10 + (c & 15U); return neg ? -(int64_t)n : n; }
template<typename T, int N> struct mat { T dat[N*N]; struct id_s {}; static const id_s id; mat(): dat{} { } mat(std::initializer_list<T> l) { int i = 0; for(auto&& x: l) dat[i++] = x; for(; i < N*N; i++) dat[i] = 0; } mat(int m): dat{} { for(int i = 0; i < N; i++) (*this)(i,i) = m; } mat(id_s) { for(int i = 0; i < N; i++) for(int j = 0; j < N; j++) dat[N*i + j] = +(i==j); } T& operator()(int i, int j) { return dat[N*i + j]; } const T& operator()(int i, int j) const { return dat[N*i + j]; } mat operator*(const mat& o) { mat r; for(int i = 0; i < N; i++) for(int j = 0; j < N; j++) for(int k = 0; k < N; k++) r(i,j) += (*this)(i,k) * o(k,j); return r; } mat operator+(const mat& o) { mat r; for(int i = 0; i < N*N; i++) r.dat[i] = dat[i] + o.dat[i]; return r; } };
template<typename V, typename Op, bool hasID=false> struct bitsg { V* dat = nullptr; typedef size_t I; size_t size; template<typename It> void init(size_t n, It a, It b) { delete[] dat; size = n; dat = new V[datlen()]; I i = 0; for(; a != b; a++) dat[i++] = *a; if(hasID) { for(; i < n; i++) dat[i++] = V{}; } calcfromelem(); } bitsg() {} template<typename It> bitsg(size_t n, It a, It b) { init(n, a, b); } ~bitsg() { delete[] dat; } size_t datlen() { return 2*size - __builtin_popcount(size); } void calcfromelem() { V* p = dat; for(I n = size; n > 1; n >>= 1) { for(I i = 0; i < n/2; i++) { p[n + i] = Op()(p[2*i], p[2*i+1]); } p += n; } } V sum(I a, I b) const { assert(a >= 0 && b >= a && b <= size); V ra, rb; bool ha = false, hb = false; size_t sz = size; V* dp = dat; while(b > a) { if(a & 1) { if(ha) ra = Op()(ra, dp[a]); else ha = true, ra = dp[a]; a++; } if(b & 1) { if(hb) rb = Op()(dp[b-1], rb); else hb = true, rb = dp[b-1]; b--; } dp += sz; sz >>= 1; a >>= 1; b >>= 1; } if(ha && hb) return Op()(ra, rb); if(ha) return ra; if(hb) return rb; assert(hasID); return V{}; } const V& get(I i) const { assert(i < size); return dat[i]; } void set(I i, const V& v) { V& cur = dat[i] = v; V*p = dat; size_t sz = size; for( ; i/2 < sz/2 ; ) { V val; if(i & 1) val = Op()(p[i-1], cur); else val = Op()(cur, p[i+1]); p += sz; cur = p[i >>= 1] = val; sz >>= 1; } } };

typedef mat<double, 3> M;

using namespace std;

M rot(int a) {
    double ra = a * (3.14159265358979323846 / 180);
    double c = cos(ra), s = sin(ra);
    return M{c, -s, 0,
             s,  c, 0,
             0,  0, 1};
}

M trans(int d) {
    return M{1, 0, d,
             0, 1, 0,
             0, 0, 1};
}

struct tim {
    M operator()(M& a, M& b) {return a*b;}
};

int main()
{
    ios_base::sync_with_stdio(0);

    int n=IU, m=IU;

    bitsg<M, tim > b;
     b.size = 2*n;
    b.dat = new M[b.datlen()];

    for(int i=0; i<n; i++)
        b.dat[2*i] = M(M::id),
        b.dat[2*i+1] = trans(1);
    b.calcfromelem();

    while(m--) {
        int x=IU, y=IU-1, z=IU;
        if(x == 1)
            b.set(2*y+1, b.dat[2*y+1] * trans(z));
        else
            b.set(2*y, b.dat[2*y] * rot(-z));
        M t = b.sum(0, 2*n);
        printf("%.12f %.12f\n", t.dat[2], t.dat[5]);
    }

    return 0;
}


#include <bits/stdc++.h>

#ifdef _WIN32
#define getchar_unlocked getchar
#endif
#define II (read32())
#define IU (readu32())
#define IL (read64())
#define IUL (readu64())
uint32_t readu32() { int c; while((c = getchar_unlocked()) < '0'); uint32_t n = c & 15U; while((c = getchar_unlocked()) >= '0') n = n * 10 + (c & 15U); return n; } uint64_t readu64() { int c; while((c = getchar_unlocked()) < '0'); uint64_t n = c & 15U; while((c = getchar_unlocked()) >= '0') n = n * 10 + (c & 15U); return n; } int32_t read32() { int c; while((c = getchar_unlocked()) < '-'); bool neg = c == '-'; if(neg) c = getchar_unlocked(); uint32_t n = c & 15U; while((c = getchar_unlocked()) >= '0') n = n * 10 + (c & 15U); return neg ? -(int32_t)n : n; } int64_t read64() { int c; while((c = getchar_unlocked()) < '-'); bool neg = c == '-'; if(neg) c = getchar_unlocked(); uint64_t n = c & 15; while((c = getchar_unlocked()) >= '0') n = n * 10 + (c & 15U); return neg ? -(int64_t)n : n; }

using namespace std;

#define N 100000
double x[N], y[N];
double d2(double x1,double y1,double x2,double y2) {
    return(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
}
int main()
{
    ios_base::sync_with_stdio(0);
    int n=IU;
    for(int i=0;i<n;i++)
        x[i] = II, y[i] = II;
    for(int i=n; i--;) {
        y[i] -= y[0];
        x[i] -= x[0];
    }
    double d2min = 1e99;
    int imin;
    for(int i=1; i<n; i++) {
        double d = d2(x[0],y[0],x[i],y[i]);
        if(d < d2min) d2min=d, imin=i;
    }
    double pdmin = 1e99;
    int pimin;
    double vx = x[imin]-x[0], vy = y[imin]-y[0];
    double v2 = vx*vx + vy*vy;
    for(int i=0; i<n; i++) {
        double c = (x[i] * vx + y[i] * vy) / v2;
        double pd = d2(c*vx, c*vy, x[i], y[i]);
        if(pd > 1e-20 && pd < pdmin) {
            pimin = i;
            pdmin = pd;
        }
    }
    printf("%d %d %d", 1, imin+1, pimin+1);
    return 0;
}


#include <bits/stdc++.h>
#include "C:/Users/dirac/Documents/c++/mylib/src/bitsg.cpp"

#ifdef _WIN32
#define getchar_unlocked getchar
#endif
#define II (read32())
#define IU (readu32())
#define IL (read64())
#define IUL (readu64())
uint32_t readu32() { int c; while((c = getchar_unlocked()) < '0'); uint32_t n = c & 15U; while((c = getchar_unlocked()) >= '0') n = n * 10 + (c & 15U); return n; } uint64_t readu64() { int c; while((c = getchar_unlocked()) < '0'); uint64_t n = c & 15U; while((c = getchar_unlocked()) >= '0') n = n * 10 + (c & 15U); return n; } int32_t read32() { int c; while((c = getchar_unlocked()) < '-'); bool neg = c == '-'; if(neg) c = getchar_unlocked(); uint32_t n = c & 15U; while((c = getchar_unlocked()) >= '0') n = n * 10 + (c & 15U); return neg ? -(int32_t)n : n; } int64_t read64() { int c; while((c = getchar_unlocked()) < '-'); bool neg = c == '-'; if(neg) c = getchar_unlocked(); uint64_t n = c & 15; while((c = getchar_unlocked()) >= '0') n = n * 10 + (c & 15U); return neg ? -(int64_t)n : n; }
template<typename T, int N> struct mat { T dat[N*N]; struct id_s {}; static const id_s id; mat(): dat{} { } mat(std::initializer_list<T> l) { int i = 0; for(auto&& x: l) dat[i++] = x; for(; i < N*N; i++) dat[i] = 0; } mat(int m): dat{} { for(int i = 0; i < N; i++) (*this)(i,i) = m; } mat(id_s) { for(int i = 0; i < N; i++) for(int j = 0; j < N; j++) dat[N*i + j] = +(i==j); } T& operator()(int i, int j) { return dat[N*i + j]; } const T& operator()(int i, int j) const { return dat[N*i + j]; } mat operator*(const mat& o) { mat r; for(int i = 0; i < N; i++) for(int j = 0; j < N; j++) for(int k = 0; k < N; k++) r(i,j) += (*this)(i,k) * o(k,j); return r; } mat operator+(const mat& o) { mat r; for(int i = 0; i < N*N; i++) r.dat[i] = dat[i] + o.dat[i]; return r; } };

typedef mat<double, 3> M;

using namespace std;

M rot(int a) {
    double ra = a * (3.14159265358979323846 / 180);
    double c = cos(ra), s = sin(ra);
    return M{c, -s, 0,
             s,  c, 0,
             0,  0, 1};
}

M trans(int d) {
    return M{1, 0, d,
             0, 1, 0,
             0, 0, 1};
}

struct tim {
    M operator()(M& a, M& b) {return a*b;}
};

int main()
{
    ios_base::sync_with_stdio(0);

    int n=IU, m=IU;

    bitsg<M, tim > b;
     b.size = 2*n;
    b.dat = new M[b.datlen()];

    for(int i=0; i<n; i++)
        b.dat[2*i] = M(M::id),
        b.dat[2*i+1] = trans(1);
    b.calcfromelem();

    while(m--) {
        int x=IU, y=IU-1, z=IU;
        if(x == 1)
            b.set(2*y+1, b.dat[2*y+1] * trans(z));
        else
            b.set(2*y, b.dat[2*y] * rot(-z));
        M t = b.sum(0, 2*n);
        printf("%.12f %.12f\n", t.dat[2], t.dat[5]);
    }

    return 0;
}


#include <bits/stdc++.h>
#define SZ(X) ((int)(X).size())
#define ALL(X) (X).begin(), (X).end()
#define REP(I, N) for (int I = 0; I < (N); ++I)
#define REPP(I, A, B) for (int I = (A); I < (B); ++I)
#define RI(X) scanf("%d", &(X))
#define RII(X, Y) scanf("%d%d", &(X), &(Y))
#define RIII(X, Y, Z) scanf("%d%d%d", &(X), &(Y), &(Z))
#define DRI(X) int (X); scanf("%d", &X)
#define DRII(X, Y) int X, Y; scanf("%d%d", &X, &Y)
#define DRIII(X, Y, Z) int X, Y, Z; scanf("%d%d%d", &X, &Y, &Z)
#define RS(X) scanf("%s", (X))
#define CASET int ___T, case_n = 1; scanf("%d ", &___T); while (___T-- > 0)
#define MP make_pair
#define PB push_back
#define MS0(X) memset((X), 0, sizeof((X)))
#define MS1(X) memset((X), -1, sizeof((X)))
#define LEN(X) strlen(X)
#define PII pair<int,int>
#define VI vector<int>
#define VPII vector<pair<int,int> >
#define PLL pair<long long,long long>
#define VPLL vector<pair<long long,long long> >
#define F first
#define S second
typedef long long LL;
using namespace std;
const int MOD = 1e9+7;
const int SIZE = 1e6+10;
const int INF = 2147483647;
int a[SIZE];

int BIT[SIZE];
void ins(int x,int v){
    for(;x<SIZE;x+=x&-x)BIT[x]+=v;
}
int qq(int x){
    int res=0;
    for(;x;x-=x&-x)res+=BIT[x];
    return res;
}
const double EPS=1e-12;
const double PI=acos(-1);
struct Point{
    double x,y;
    Point(double _x=0,double _y=0){x=_x;y=_y;}
    Point operator-(const Point& b){return Point(x-b.x,y-b.y);}
    Point operator+(const Point& b){return Point(x+b.x,y+b.y);}
    Point operator*(const double v){return Point(x*v,y*v);}
    double operator*(const Point& b){return x*b.y-y*b.x;}
    double operator^(const Point& b){return x*b.x+y*b.y;}
    bool operator<(const Point& b)const{
        if(fabs(x-b.x)<EPS){
            if(fabs(y-b.y)<EPS)return 0;
            return y<b.y;
        }
        return x<b.x;
    }
    Point rotate(double v){return Point(x*cos(v)-y*sin(v),x*sin(v)+y*cos(v));}
    double angle(){return atan2(y,x);}
    double dis(){return sqrt(x*x+y*y);}
    void scan(){scanf("%lf%lf",&x,&y);}
    void print(){printf("%.9f %.9f\n",x,y);}
};
struct SegTree{
    Point vv[SIZE<<2];
    int len[SIZE];
    int n;
    void build(int L,int R,int id){
        if(L==R){
            vv[id]=Point(len[L],0);
            return;
        }
        int mm=(L+R)>>1;
        build(L,mm,id<<1);
        build(mm+1,R,(id<<1)|1);
        vv[id]=vv[id*2]+(vv[id*2+1].rotate((qq(mm+1)-qq(L))/180.*PI));
    }
    void init(int _n){
        n=_n;
        REP(i,n){
            len[i+1]=1;
        }
        build(1,n,1);
    }
    int me,v;
    void _edit(int L,int R,int id){
        if(L==R){
            vv[id]=Point(len[L],0);
            return;
        }
        int mm=(L+R)>>1;
        if(me<=mm)_edit(L,mm,id<<1);
        else _edit(mm+1,R,(id<<1)|1);
        vv[id]=vv[id*2]+(vv[id*2+1].rotate((qq(mm+1)-qq(L))/180.*PI));
    }
    void edit(int _x){
        me=_x;
        _edit(1,n,1);
    }
}seg;

int main(){
    DRII(n,m);
    seg.init(n);
    while(m--){
        DRIII(x,y,z);
        if(x==1){
            seg.len[y]+=z;
        }
        else{
            ins(y,-z);
        }
        seg.edit(y);
        if(y!=1)seg.edit(y-1);
        seg.vv[1].rotate(qq(1)/180.*PI).print();
    }
    return 0;
}


#include <bits/stdc++.h>
#define SZ(X) ((int)(X).size())
#define ALL(X) (X).begin(), (X).end()
#define REP(I, N) for (int I = 0; I < (N); ++I)
#define REPP(I, A, B) for (int I = (A); I < (B); ++I)
#define RI(X) scanf("%d", &(X))
#define RII(X, Y) scanf("%d%d", &(X), &(Y))
#define RIII(X, Y, Z) scanf("%d%d%d", &(X), &(Y), &(Z))
#define DRI(X) int (X); scanf("%d", &X)
#define DRII(X, Y) int X, Y; scanf("%d%d", &X, &Y)
#define DRIII(X, Y, Z) int X, Y, Z; scanf("%d%d%d", &X, &Y, &Z)
#define RS(X) scanf("%s", (X))
#define CASET int ___T, case_n = 1; scanf("%d ", &___T); while (___T-- > 0)
#define MP make_pair
#define PB push_back
#define MS0(X) memset((X), 0, sizeof((X)))
#define MS1(X) memset((X), -1, sizeof((X)))
#define LEN(X) strlen(X)
#define PII pair<int,int>
#define VI vector<int>
#define VPII vector<pair<int,int> >
#define PLL pair<long long,long long>
#define VPLL vector<pair<long long,long long> >
#define F first
#define S second
typedef long long LL;
using namespace std;
const int MOD = 1e9+7;
const int SIZE = 1e6+10;
const int INF = 2147483647;
int a[SIZE];

int BIT[SIZE];
void ins(int x,int v){
    for(;x<SIZE;x+=x&-x)BIT[x]+=v;
}
int qq(int x){
    int res=0;
    for(;x;x-=x&-x)res+=BIT[x];
    return res;
}
const double EPS=1e-12;
const double PI=acos(-1);
struct Point{
    double x,y;
    Point(double _x=0,double _y=0){x=_x;y=_y;}
    Point operator-(const Point& b){return Point(x-b.x,y-b.y);}
    Point operator+(const Point& b){return Point(x+b.x,y+b.y);}
    Point operator*(const double v){return Point(x*v,y*v);}
    double operator*(const Point& b){return x*b.y-y*b.x;}
    double operator^(const Point& b){return x*b.x+y*b.y;}
    bool operator<(const Point& b)const{
        if(fabs(x-b.x)<EPS){
            if(fabs(y-b.y)<EPS)return 0;
            return y<b.y;
        }
        return x<b.x;
    }
    Point rotate(double v){return Point(x*cos(v)-y*sin(v),x*sin(v)+y*cos(v));}
    double angle(){return atan2(y,x);}
    double dis(){return sqrt(x*x+y*y);}
    void scan(){scanf("%lf%lf",&x,&y);}
    void print(){printf("%.9f %.9f\n",x,y);}
};
struct SegTree{
    Point vv[SIZE<<2];
    int len[SIZE];
    int n;
    void build(int L,int R,int id){
        if(L==R){
            vv[id]=Point(len[L],0);
            return;
        }
        int mm=(L+R)>>1;
        build(L,mm,id<<1);
        build(mm+1,R,(id<<1)|1);
        vv[id]=vv[id*2]+(vv[id*2+1].rotate((qq(mm+1)-qq(L-1))/180.*PI));
    }
    void init(int _n){
        n=_n;
        REP(i,n){
            len[i+1]=1;
        }
        build(1,n,1);
    }
    int me,v;
    void _edit(int L,int R,int id){
        if(L==R){
            vv[id]=Point(len[L],0);
            return;
        }
        int mm=(L+R)>>1;
        if(me<=mm)_edit(L,mm,id<<1);
        else _edit(mm+1,R,(id<<1)|1);
        vv[id]=vv[id*2]+(vv[id*2+1].rotate((qq(mm+1)-qq(L-1))/180.*PI));
    }
    void edit(int _x){
        me=_x;
        _edit(1,n,1);
    }
}seg;

int main(){
    DRII(n,m);
    seg.init(n);
    while(m--){
        DRIII(x,y,z);
        if(x==1){
            seg.len[y]+=z;
        }
        else{
            ins(y,-z);
        }
        seg.edit(y);
        seg.vv[1].rotate(qq(1)).print();
    }
    return 0;
}


#include <bits/stdc++.h>
#define SZ(X) ((int)(X).size())
#define ALL(X) (X).begin(), (X).end()
#define REP(I, N) for (int I = 0; I < (N); ++I)
#define REPP(I, A, B) for (int I = (A); I < (B); ++I)
#define RI(X) scanf("%d", &(X))
#define RII(X, Y) scanf("%d%d", &(X), &(Y))
#define RIII(X, Y, Z) scanf("%d%d%d", &(X), &(Y), &(Z))
#define DRI(X) int (X); scanf("%d", &X)
#define DRII(X, Y) int X, Y; scanf("%d%d", &X, &Y)
#define DRIII(X, Y, Z) int X, Y, Z; scanf("%d%d%d", &X, &Y, &Z)
#define RS(X) scanf("%s", (X))
#define CASET int ___T, case_n = 1; scanf("%d ", &___T); while (___T-- > 0)
#define MP make_pair
#define PB push_back
#define MS0(X) memset((X), 0, sizeof((X)))
#define MS1(X) memset((X), -1, sizeof((X)))
#define LEN(X) strlen(X)
#define PII pair<int,int>
#define VI vector<int>
#define VPII vector<pair<int,int> >
#define PLL pair<long long,long long>
#define VPLL vector<pair<long long,long long> >
#define F first
#define S second
typedef long long LL;
using namespace std;
const int MOD = 1e9+7;
const int SIZE = 1e6+10;
const int INF = 2147483647;
int a[SIZE];

int BIT[SIZE];
void ins(int x,int v){
    for(;x<SIZE;x+=x&-x)BIT[x]+=v;
}
int qq(int x){
    int res=0;
    for(;x;x-=x&-x)res+=BIT[x];
    return res;
}
const double EPS=1e-12;
const double PI=acos(-1);
struct Point{
    double x,y;
    Point(double _x=0,double _y=0){x=_x;y=_y;}
    Point operator-(const Point& b){return Point(x-b.x,y-b.y);}
    Point operator+(const Point& b){return Point(x+b.x,y+b.y);}
    Point operator*(const double v){return Point(x*v,y*v);}
    double operator*(const Point& b){return x*b.y-y*b.x;}
    double operator^(const Point& b){return x*b.x+y*b.y;}
    bool operator<(const Point& b)const{
        if(fabs(x-b.x)<EPS){
            if(fabs(y-b.y)<EPS)return 0;
            return y<b.y;
        }
        return x<b.x;
    }
    Point rotate(double v){return Point(x*cos(v)-y*sin(v),x*sin(v)+y*cos(v));}
    double angle(){return atan2(y,x);}
    double dis(){return sqrt(x*x+y*y);}
    void scan(){scanf("%lf%lf",&x,&y);}
    void print(){printf("%.9f %.9f\n",x,y);}
};
struct SegTree{
    Point vv[SIZE<<2];
    int len[SIZE];
    int n;
    void build(int L,int R,int id){
        if(L==R){
            vv[id]=Point(len[L],0);
            return;
        }
        int mm=(L+R)>>1;
        build(L,mm,id<<1);
        build(mm+1,R,(id<<1)|1);
        vv[id]=vv[id*2]+(vv[id*2+1].rotate((qq(mm+1)-qq(L))/180.*PI));
    }
    void init(int _n){
        n=_n;
        REP(i,n){
            len[i+1]=1;
        }
        build(1,n,1);
    }
    int me,v;
    void _edit(int L,int R,int id){
        if(L==R){
            vv[id]=Point(len[L],0);
            return;
        }
        int mm=(L+R)>>1;
        if(me<=mm)_edit(L,mm,id<<1);
        else _edit(mm+1,R,(id<<1)|1);
        vv[id]=vv[id*2]+(vv[id*2+1].rotate((qq(mm+1)-qq(L))/180.*PI));
    }
    void edit(int _x){
        me=_x;
        _edit(1,n,1);
    }
}seg;

int main(){
    DRII(n,m);
    seg.init(n);
    while(m--){
        DRIII(x,y,z);
        if(x==1){
            seg.len[y]+=z;
        }
        else{
            ins(y,-z);
        }
        seg.edit(y);
        seg.vv[1].rotate(qq(1)).print();
    }
    return 0;
}


#include <bits/stdc++.h>
#define SZ(X) ((int)(X).size())
#define ALL(X) (X).begin(), (X).end()
#define REP(I, N) for (int I = 0; I < (N); ++I)
#define REPP(I, A, B) for (int I = (A); I < (B); ++I)
#define RI(X) scanf("%d", &(X))
#define RII(X, Y) scanf("%d%d", &(X), &(Y))
#define RIII(X, Y, Z) scanf("%d%d%d", &(X), &(Y), &(Z))
#define DRI(X) int (X); scanf("%d", &X)
#define DRII(X, Y) int X, Y; scanf("%d%d", &X, &Y)
#define DRIII(X, Y, Z) int X, Y, Z; scanf("%d%d%d", &X, &Y, &Z)
#define RS(X) scanf("%s", (X))
#define CASET int ___T, case_n = 1; scanf("%d ", &___T); while (___T-- > 0)
#define MP make_pair
#define PB push_back
#define MS0(X) memset((X), 0, sizeof((X)))
#define MS1(X) memset((X), -1, sizeof((X)))
#define LEN(X) strlen(X)
#define PII pair<int,int>
#define VI vector<int>
#define VPII vector<pair<int,int> >
#define PLL pair<long long,long long>
#define VPLL vector<pair<long long,long long> >
#define F first
#define S second
typedef long long LL;
using namespace std;
const int MOD = 1e9+7;
const int SIZE = 1e6+10;
const int INF = 2147483647;
int a[SIZE];

int BIT[SIZE];
void ins(int x,int v){
    for(;x<SIZE;x+=x&-x)BIT[x]+=v;
}
int qq(int x){
    int res=0;
    for(;x;x-=x&-x)res+=BIT[x];
    return res;
}
const double EPS=1e-12;
const double PI=acos(-1);
struct Point{
    double x,y;
    Point(double _x=0,double _y=0){x=_x;y=_y;}
    Point operator-(const Point& b){return Point(x-b.x,y-b.y);}
    Point operator+(const Point& b){return Point(x+b.x,y+b.y);}
    Point operator*(const double v){return Point(x*v,y*v);}
    double operator*(const Point& b){return x*b.y-y*b.x;}
    double operator^(const Point& b){return x*b.x+y*b.y;}
    bool operator<(const Point& b)const{
        if(fabs(x-b.x)<EPS){
            if(fabs(y-b.y)<EPS)return 0;
            return y<b.y;
        }
        return x<b.x;
    }
    Point rotate(double v){return Point(x*cos(v)-y*sin(v),x*sin(v)+y*cos(v));}
    double angle(){return atan2(y,x);}
    double dis(){return sqrt(x*x+y*y);}
    void scan(){scanf("%lf%lf",&x,&y);}
    void print(){printf("%.9f %.9f\n",x,y);}
};
struct SegTree{
    Point vv[SIZE<<2];
    int len[SIZE];
    int n;
    void build(int L,int R,int id){
        if(L==R){
            vv[id]=Point(len[L],0);
            return;
        }
        int mm=(L+R)>>1;
        build(L,mm,id<<1);
        build(mm+1,R,(id<<1)|1);
        vv[id]=vv[id*2]+(vv[id*2+1].rotate((qq(mm+1)-qq(L))/180.*PI));
    }
    void init(int _n){
        n=_n;
        REP(i,n){
            len[i+1]=1;
        }
        build(1,n,1);
    }
    int me,v;
    void _edit(int L,int R,int id){
        if(L==R){
            vv[id]=Point(len[L],0);
            return;
        }
        int mm=(L+R)>>1;
        if(me<=mm)_edit(L,mm,id<<1);
        else _edit(mm+1,R,(id<<1)|1);
        vv[id]=vv[id*2]+(vv[id*2+1].rotate((qq(mm+1)-qq(L))/180.*PI));
    }
    void edit(int _x){
        me=_x;
        _edit(1,n,1);
    }
}seg;

int main(){
    DRII(n,m);
    seg.init(n);
    while(m--){
        DRIII(x,y,z);
        if(x==1){
            seg.len[y]+=z;
        }
        else{
            ins(y,-z);
        }
        seg.edit(y);
        if(y!=1)seg.edit(y-1);
        seg.vv[1].rotate(qq(1)).print();
    }
    return 0;
}


#include <cstdio>
#include <cmath>
#include <cstring>
#include <cassert>
#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

#define TRACE(x) cerr << #x << " = " << x << endl

typedef long long ll;
typedef pair<double, double> P;
#define X first
#define Y second

const int MAX = 301000, KOR = 1000;
const double PI = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679;
const double EPS = 1e-6;

struct ev {
  int st, ind; //1 = rot, 2 = trans
  P prom;
};

bool operator < (const ev &a, const ev &b)
{
  return a.ind < b.ind;
}

vector <ev> E;
P poc[MAX], pros[MAX], p[MAX];
int n;
vector <int> Bit;
//double zadkut = -1e9, cc, ss;
double cc[400], ss[400];
int rac;
double sumud;

P Rot(P toc, int an)
{
/*  if (abs(an - zadkut) > EPS) {
    rac++;
    zadkut = an;
    cc = cos(an);
    ss = sin(an);
//    ss = sqrt(1 - cc);
  }*/
//  double cc = cos(an), ss = sin(an);
  return P(toc.X * cc[an] - toc.Y * ss[an],
           toc.Y * cc[an] + toc.X * ss[an]);
}

P Trans(P toc, P pom)
{
  return P(toc.X + pom.X, toc.Y + pom.Y);
}

P Toc(int prosli, int ja, int an, P polje[MAX])
{
//  fprintf(stderr, "TOC %d %lf %lf    %d %lf %lf    %lf\n", prosli, pros[prosli].X, pros[prosli].Y,
  //                                                         ja, pros[ja].X, pros[ja].Y, an);
  return Trans(p[prosli], Rot(P(polje[ja].X - polje[prosli].X, polje[ja].Y - polje[prosli].Y), an));
}

inline double Sq(double x)
{
  return x * x;
}

double Dist(P a, P b)
{
  return sqrt(Sq(a.X - b.X) + Sq(a.Y - b.Y));
}

void Ispis()
{
  for (int j=0; j<n; j++)
    fprintf(stderr, "%d   %lf %lf\n", j, p[j].X, p[j].Y);
  fprintf(stderr, "\n\n");
}

void Event(ev tmp)
{
//  printf("PRIJE\n");
  //Ispis();

  for (int i=0; i<(int) Bit.size(); i++)
    pros[Bit[i]] = p[Bit[i]];

  for (int i=0; i<(int) Bit.size(); i++) {
    if (Bit[i] > tmp.ind) {
      if (tmp.st == 1)
        p[Bit[i]] = Toc(tmp.ind, Bit[i], (int) (0.5 + tmp.prom.X), pros);
      else
        p[Bit[i]] = Trans(p[Bit[i]], tmp.prom);
    }
  }

  E.push_back(tmp);

  if (tmp.st == 2)
    sumud += tmp.prom.X + tmp.prom.Y;

//  printf("POSLIJE\n");
}

void Rebuild()
{
  int zad = 0;
  int an = 0;

//  Ispis();

  sort(E.begin(), E.end());
  for (int i=0; i<(int) Bit.size(); i++)
    pros[Bit[i]] = p[Bit[i]];

  for (int i=0, j=0, k=0; i<n; i++) {
    for (; j<(int) E.size() && E[j].ind == i; j++)
      if (E[j].st == 1)
        an = ((int) (an + E[j].prom.X + 0.5)) % 360;

    if (k < (int) Bit.size() && Bit[k] == i) {
      zad = i;
      k++;
    }
    else {
//      fprintf(stderr, "II %d\n", i);
      p[i] = Toc(zad, i, an, poc);
//      if (
//      if (i < Bit[3] && i > Bit[2] && i - Bit[2] < 5)
  //      fprintf(stderr, "PPP %d    %lf %lf\n", i, p[i].X, p[i].Y);
    }
  }

  memcpy(poc, p, sizeof p);
  E.clear();
  //Ispis();
}

int qst[MAX], qind[MAX], qval[MAX];

int main()
{
  for (int i=0; i<360; i++) {
    cc[i] = cos(-PI / 180 * i);
    ss[i] = sin(-PI / 180 * i);
  }

  int m;

 scanf("%d%d", &n, &m); n++;
//  n = 300000, m = 300000; n++;

  for (int i=0; i<n; i++)
   p[i] = P(i, 0);

  sumud = p[n-1].X;

  for (int i=0; i<m; i++) {
    //qst[i] = rand() % 2 + 1;
  //  qind[i] = rand() % (n - 5) + 2;
//    qval[i] = rand() % 300 + 1;
//    if (i < 5)
  //    fprintf(stderr, "%d %d %d\n", qst[i], qind[i], qval[i]);
    scanf("%d%d%d", &qst[i], &qind[i], &qval[i]); qind[i]--;
    qst[i] = 3 - qst[i];
  }

  memcpy(poc, p, sizeof p);

  for (int i=0; i<m; i++) {
    if (!(i % KOR)) {
      TRACE(i);
      Bit.clear();

      for (int j=i; j<i+KOR+1; j++) {
        Bit.push_back(qind[j]);
        if (qst[j] == 2)
          Bit.push_back(qind[j]+1);
      }

      Bit.push_back(0);
      Bit.push_back(n-1);
      sort(Bit.begin(), Bit.end());
      Bit.resize(unique(Bit.begin(), Bit.end()) - Bit.begin());
      memcpy(pros, p, sizeof pros);

//      if (i)
  //      fprintf(stderr, "RAC PO I %lf\n", (double) rac / i);

//      fprintf(stderr, "SAJZB %d\n", (int) Bit.size());
  //    fprintf(stderr, "SAJZE %d\n", (int) E.size());
    }

    int st = qst[i], ind = qind[i];

    if (qst[i] == 1) {
//      double an = -PI / 180 * qval[i];
      Event(ev { st, ind, P(qval[i], -1) });
    }
    else {
      P raz = P(p[ind+1].X - p[ind].X, p[ind+1].Y - p[ind].Y);
      double kut = atan2(raz.Y, raz.X);
      P smjer = P(cos(kut), sin(kut));
  //    double dd = Dist(P(0, 0), raz);
    //  P smjer = P(raz.X / dd, raz.Y / dd);
//      fprintf(stderr, "SMJER %lf %lf\n", smjer.X, smjer.Y);
  //    TRACE(qval[i]);
//      fprintf(stderr, "EV %lf %lf\n", smjer.X * qval[i], smjer.Y * qval[i]);
      Event(ev { st, ind, P(smjer.X * qval[i], smjer.Y * qval[i]) });
    }

    if (E.size() == KOR) {
      Rebuild();
      E.clear();
      memcpy(pros, p, sizeof pros);
    }

/*    if (p[n-1].X > 1e15 || p[n-1].X < -1e15) {
      TRACE(p[n-1].X);
      TRACE(i);
      break;
    }*/

    //if (Dist(p[n-1], P(0, 0)) - EPS > sumud) {
      //fprintf(stderr, "NEIN %d %lf %lf\n", i, sumud, Dist(p[n-1], P(0, 0)));
//      return 0;
  //  }
    printf("%.10lf %.10lf\n", p[n-1].X, p[n-1].Y);
//    if (i == 1)
  //    break;
  }

  //TRACE(rac);

  return 0;
}


#include <cstdio>
#include <cmath>
#include <cstring>
#include <cassert>
#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

#define TRACE(x) cerr << #x << " = " << x << endl

typedef long long ll;
typedef pair<double, double> P;
#define X first
#define Y second

const int MAX = 301000, KOR = 1000;
const double PI = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679;
const double EPS = 1e-6;

struct ev {
  int st, ind; //1 = rot, 2 = trans
  P prom;
};

bool operator < (const ev &a, const ev &b)
{
  return a.ind < b.ind;
}

vector <ev> E;
P poc[MAX], pros[MAX], p[MAX];
int n;
vector <int> Bit;
double zadkut = -1e9, cc, ss;
int rac;
double sumud;

P Rot(P toc, double an)
{
  if (abs(an - zadkut) > EPS) {
    rac++;
    zadkut = an;
    cc = cos(an);
    ss = sin(an);
    //ss = sqrt(1 - cc);
  }
//  double cc = cos(an), ss = sin(an);
  return P(toc.X * cc - toc.Y * ss,
           toc.Y * cc + toc.X * ss);
}

P Trans(P toc, P pom)
{
  return P(toc.X + pom.X, toc.Y + pom.Y);
}

P Toc(int prosli, int ja, double an, P polje[MAX])
{
//  fprintf(stderr, "TOC %d %lf %lf    %d %lf %lf    %lf\n", prosli, pros[prosli].X, pros[prosli].Y,
  //                                                         ja, pros[ja].X, pros[ja].Y, an);
  return Trans(p[prosli], Rot(P(polje[ja].X - polje[prosli].X, polje[ja].Y - polje[prosli].Y), an));
}

inline double Sq(double x)
{
  return x * x;
}

double Dist(P a, P b)
{
  return sqrt(Sq(a.X - b.X) + Sq(a.Y - b.Y));
}

void Ispis()
{
  for (int j=0; j<n; j++)
    fprintf(stderr, "%d   %lf %lf\n", j, p[j].X, p[j].Y);
  fprintf(stderr, "\n\n");
}

void Event(ev tmp)
{
//  printf("PRIJE\n");
  //Ispis();

  for (int i=0; i<(int) Bit.size(); i++)
    pros[Bit[i]] = p[Bit[i]];

  for (int i=0; i<(int) Bit.size(); i++) {
    if (Bit[i] > tmp.ind) {
      if (tmp.st == 1)
        p[Bit[i]] = Toc(tmp.ind, Bit[i], tmp.prom.X, pros);
      else
        p[Bit[i]] = Trans(p[Bit[i]], tmp.prom);
    }
  }

  E.push_back(tmp);

  if (tmp.st == 2)
    sumud += tmp.prom.X + tmp.prom.Y;

//  printf("POSLIJE\n");
}

void Rebuild()
{
  int zad = 0;
  double an = 0;

//  Ispis();

  sort(E.begin(), E.end());
  for (int i=0; i<(int) Bit.size(); i++)
    pros[Bit[i]] = p[Bit[i]];

  for (int i=0, j=0, k=0; i<n; i++) {
    for (; j<(int) E.size() && E[j].ind == i; j++)
      if (E[j].st == 1)
        an += E[j].prom.X;

    if (k < (int) Bit.size() && Bit[k] == i) {
      zad = i;
      k++;
    }
    else {
//      fprintf(stderr, "II %d\n", i);
      p[i] = Toc(zad, i, an, poc);
//      if (
//      if (i < Bit[3] && i > Bit[2] && i - Bit[2] < 5)
  //      fprintf(stderr, "PPP %d    %lf %lf\n", i, p[i].X, p[i].Y);
    }
  }

  memcpy(poc, p, sizeof p);
  E.clear();
  //Ispis();
}

int qst[MAX], qind[MAX], qval[MAX];

int main()
{
  int m;

  scanf("%d%d", &n, &m); n++;
//  n = 300000, m = 300000; n++;

  for (int i=0; i<n; i++)
   p[i] = P(i, 0);

  sumud = p[n-1].X;

  for (int i=0; i<m; i++) {
    qst[i] = rand() % 2 + 1;
    qind[i] = rand() % (n - 5) + 2;
    qval[i] = rand() % 300 + 1;
//    if (i < 5)
  //    fprintf(stderr, "%d %d %d\n", qst[i], qind[i], qval[i]);
    scanf("%d%d%d", &qst[i], &qind[i], &qval[i]); qind[i]--;
    qst[i] = 3 - qst[i];
  }

  memcpy(poc, p, sizeof p);

  for (int i=0; i<m; i++) {
    if (!(i % KOR)) {
      //TRACE(i);
      Bit.clear();

      for (int j=i; j<i+KOR+1; j++) {
        Bit.push_back(qind[j]);
        if (qst[j] == 2)
          Bit.push_back(qind[j]+1);
      }

      Bit.push_back(0);
      Bit.push_back(n-1);
      sort(Bit.begin(), Bit.end());
      Bit.resize(unique(Bit.begin(), Bit.end()) - Bit.begin());
      memcpy(pros, p, sizeof pros);

//      if (i)
  //      fprintf(stderr, "RAC PO I %lf\n", (double) rac / i);

//      fprintf(stderr, "SAJZB %d\n", (int) Bit.size());
  //    fprintf(stderr, "SAJZE %d\n", (int) E.size());
    }

    int st = qst[i], ind = qind[i];

    if (qst[i] == 1) {
      double an = -PI / 180 * qval[i];
      Event(ev { st, ind, P(an, -1) });
    }
    else {
      P raz = P(p[ind+1].X - p[ind].X, p[ind+1].Y - p[ind].Y);
      double dd = Dist(P(0, 0), raz);
      P smjer = P(raz.X / dd, raz.Y / dd);
//      fprintf(stderr, "SMJER %lf %lf\n", smjer.X, smjer.Y);
  //    TRACE(qval[i]);
//      fprintf(stderr, "EV %lf %lf\n", smjer.X * qval[i], smjer.Y * qval[i]);
      Event(ev { st, ind, P(smjer.X * qval[i], smjer.Y * qval[i]) });
    }

    if (E.size() == KOR) {
      Rebuild();
      E.clear();
      memcpy(pros, p, sizeof pros);
    }

/*    if (p[n-1].X > 1e15 || p[n-1].X < -1e15) {
      TRACE(p[n-1].X);
      TRACE(i);
      break;
    }*/

    //if (Dist(p[n-1], P(0, 0)) - EPS > sumud) {
      //fprintf(stderr, "NEIN %d %lf %lf\n", i, sumud, Dist(p[n-1], P(0, 0)));
//      return 0;
  //  }
    printf("%.10lf %.10lf\n", p[n-1].X, p[n-1].Y);
//    if (i == 1)
  //    break;
  }

  //TRACE(rac);

  return 0;
}


#include <cstdio>
#include <cmath>
#include <cstring>
#include <cassert>
#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

#define TRACE(x) cerr << #x << " = " << x << endl

typedef long long ll;
typedef pair<double, double> P;
#define X first
#define Y second

const int MAX = 301000, KOR = 1000;
const double PI = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679;
const double EPS = 1e-6;

struct ev {
  int st, ind; //1 = rot, 2 = trans
  P prom;
};

bool operator < (const ev &a, const ev &b)
{
  return a.ind < b.ind;
}

vector <ev> E;
P poc[MAX], pros[MAX], p[MAX];
int n;
vector <int> Bit;
double cc[400], ss[400];

P Rot(P toc, int an)
{
  return P(toc.X * cc[an] - toc.Y * ss[an],
           toc.Y * cc[an] + toc.X * ss[an]);
}

P Trans(P toc, P pom)
{
  return P(toc.X + pom.X, toc.Y + pom.Y);
}

P Toc(int prosli, int ja, int an, P polje[MAX])
{
  return Trans(p[prosli], Rot(P(polje[ja].X - polje[prosli].X, polje[ja].Y - polje[prosli].Y), an));
}

inline double Sq(double x)
{
  return x * x;
}

double Dist(P a, P b)
{
  return sqrt(Sq(a.X - b.X) + Sq(a.Y - b.Y));
}

void Event(ev tmp)
{
  for (int i=0; i<(int) Bit.size(); i++)
    pros[Bit[i]] = p[Bit[i]];

  for (int i=0; i<(int) Bit.size(); i++) {
    if (Bit[i] > tmp.ind) {
      if (tmp.st == 1)
        p[Bit[i]] = Toc(tmp.ind, Bit[i], (int) (0.5 + tmp.prom.X), pros);
      else
        p[Bit[i]] = Trans(p[Bit[i]], tmp.prom);
    }
  }

  E.push_back(tmp);
}

void Rebuild()
{
  int zad = 0;
  int an = 0;

  sort(E.begin(), E.end());
  for (int i=0; i<(int) Bit.size(); i++)
    pros[Bit[i]] = p[Bit[i]];

  for (int i=0, j=0, k=0; i<n; i++) {
    for (; j<(int) E.size() && E[j].ind == i; j++)
      if (E[j].st == 1)
        an = ((int) (an + E[j].prom.X + 0.5)) % 360;

    if (k < (int) Bit.size() && Bit[k] == i) {
      zad = i;
      k++;
    }
    else
      p[i] = Toc(zad, i, an, poc);
  }

  memcpy(poc, p, sizeof p);
  E.clear();
}

int qst[MAX], qind[MAX], qval[MAX];

int main()
{
  for (int i=0; i<360; i++) {
    cc[i] = cos(-PI / 180 * i);
    ss[i] = sin(-PI / 180 * i);
  }

  int m;

  scanf("%d%d", &n, &m); n++;

  for (int i=0; i<n; i++)
    p[i] = P(i, 0);

  for (int i=0; i<m; i++) {
    scanf("%d%d%d", &qst[i], &qind[i], &qval[i]); qind[i]--;
    qst[i] = 3 - qst[i];
  }

  memcpy(poc, p, sizeof p);

  for (int i=0; i<m; i++) {
    if (!(i % KOR)) {
      TRACE(i);
      Bit.clear();

      for (int j=i; j<i+KOR+1; j++) {
        Bit.push_back(qind[j]);
        if (qst[j] == 2)
          Bit.push_back(qind[j]+1);
      }

      Bit.push_back(0);
      Bit.push_back(n-1);
      sort(Bit.begin(), Bit.end());
      Bit.resize(unique(Bit.begin(), Bit.end()) - Bit.begin());
      memcpy(pros, p, sizeof pros);
    }

    int st = qst[i], ind = qind[i];

    if (qst[i] == 1)
      Event(ev { st, ind, P(qval[i], -1) });
    else {
      P raz = P(p[ind+1].X - p[ind].X, p[ind+1].Y - p[ind].Y);
      double kut = atan2(raz.Y, raz.X);
      P smjer = P(cos(kut), sin(kut));
      Event(ev { st, ind, P(smjer.X * qval[i], smjer.Y * qval[i]) });
    }

    if (E.size() == KOR) {
      Rebuild();
      E.clear();
      memcpy(pros, p, sizeof pros);
    }

    printf("%.10lf %.10lf\n", p[n-1].X, p[n-1].Y);
  }

  return 0;
}


#include <stdio.h>
#include <iostream>
#include <ctime>
#include <climits>
#include <bits/stdc++.h>

#define ll long long
#define f first
#define s second
#define vii vector<pair<int, int>>

using namespace std;

struct Solver {
  const static int N = 1e6+1;

  void solve() {
    int n, m, e, mx = 0, ans = 0;
    cin >> n >> m;
    map<int, int> q;
    map<int, vector<int>> ids;
    vector<int> fids;

    for(int i = 0; i < n; i++) {
      cin >> e;
      if(e > m) { continue; }
      q[e]++;
      ids[e].push_back(i);
    }

    for(int i = 0; i <= m; i++) {
      int tmp = 0;
      for(int j = 1; j <= sqrt(i); j++) {
        if(i%j == 0) {
          tmp += q[j];
          if(j != i/j) {
            tmp += q[i/j];
          }
        }
      }
      if(tmp > mx) {
        mx = tmp;
        ans = i;
      }
    }

    for(int j = 1; j <= sqrt(ans); j++) {
      if(ans%j == 0) {
        for(auto &e : ids[j]) {
          fids.push_back(e+1);
        }
        if(j != ans/j) {
          for(auto &e : ids[ans/j]) {
            fids.push_back(e+1);
          }
        }
      }
    }

    if(ans == 0) { ans = 1; }
    cout << ans << " " << fids.size() << "\n";
    for(auto &e : fids) {
      cout << e << " ";
    }
  }
};

int main(){
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);

	#ifdef local
		freopen("input-d.txt", "r", stdin);
	#endif

  Solver sol;
  sol.solve();

	#ifdef local
    cerr << "\nTime elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
	#endif
	return 0;
}


#include <stdio.h>
#include <iostream>
#include <ctime>
#include <climits>
#include <bits/stdc++.h>

#define ll long long
#define f first
#define s second
#define vii vector<pair<int, int>>

using namespace std;

struct Solver {
  const static int N = 1e6+1;

  void solve() {
    int n, m, e, mx = 0, ans = 0;
    cin >> n >> m;
    unordered_map<int, vector<int>> ids;
    vector<int> fids;
    int q[N] = {};

    for(int i = 0; i < n; i++) {
      cin >> e;
      if(e > m) { continue; }
      q[e]++;
      ids[e].push_back(i);
    }

    for(int i = 0; i <= m; i++) {
      int tmp = 0;
      int l = 1, r = sqrt(i);
      while(l <= r) {
        if(i%l == 0) {
          tmp += q[l];
          if(l*l!=i) {
            tmp += q[i/l];
          }
        }
        if(i%r == 0) {
          tmp += q[r];
          if(r*r!=i) {
            tmp += q[i/r];
          }
        }
        l++;
        r--;
      }
      // for(int j = 1; j <= sqrt(i); j++) {
      //   if(i%j == 0) {
      //     tmp += q[j];
      //     if(j != i/j) {
      //       tmp += q[i/j];
      //     }
      //   }
      // }
      if(tmp > mx) {
        mx = tmp;
        ans = i;
      }
    }

    for(int j = 1; j <= sqrt(ans); j++) {
      if(ans%j == 0) {
        for(auto &e : ids[j]) {
          fids.push_back(e+1);
        }
        if(j != ans/j) {
          for(auto &e : ids[ans/j]) {
            fids.push_back(e+1);
          }
        }
      }
    }

    if(ans == 0) { ans = 1; }
    cout << ans << " " << fids.size() << "\n";
    sort(fids.begin(), fids.end());
    for(auto &e : fids) {
      cout << e << " ";
    }
  }
};

int main(){
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);

	#ifdef local
		freopen("input-d.txt", "r", stdin);
	#endif

  Solver sol;
  sol.solve();

	#ifdef local
    cerr << "\nTime elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
	#endif
	return 0;
}


#include <stdio.h>
#include <iostream>
#include <ctime>
#include <climits>
#include <bits/stdc++.h>

#define ll long long
#define f first
#define s second
#define vii vector<pair<int, int>>

using namespace std;

struct Solver {
  const static int N = 1e6+1;

  void solve() {
    int n, m, e, mx = 0, ans = 0;
    cin >> n >> m;
    map<int, int> q;
    map<int, vector<int>> ids;
    vector<int> fids;

    for(int i = 0; i < n; i++) {
      cin >> e;
      if(e > m) { continue; }
      q[e]++;
      ids[e].push_back(i);
    }

    for(int i = 0; i <= m; i++) {
      int tmp = 0;
      for(int j = 1; j <= sqrt(i); j++) {
        if(i%j == 0) {
          tmp += q[j];
          if(j != i/j) {
            tmp += q[i/j];
          }
        }
      }
      if(tmp > mx) {
        mx = tmp;
        ans = i;
      }
    }

    for(int j = 1; j <= sqrt(ans); j++) {
      if(ans%j == 0) {
        for(auto &e : ids[j]) {
          fids.push_back(e+1);
        }
        if(j != ans/j) {
          for(auto &e : ids[ans/j]) {
            fids.push_back(e+1);
          }
        }
      }
    }

    if(ans == 0) { ans = 1; }
    cout << ans << " " << fids.size() << "\n";
    sort(fids.begin(), fids.end());
    for(auto &e : fids) {
      cout << e << " ";
    }
  }
};

int main(){
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);

	#ifdef local
		freopen("input-d.txt", "r", stdin);
	#endif

  Solver sol;
  sol.solve();

	#ifdef local
    cerr << "\nTime elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
	#endif
	return 0;
}


#include<bits/stdc++.h>
#define ll long long
#define push_back emplace_back
using namespace std;
int freq[1000006], ara[1000006];
ll mem[1000006];
int main()
{
    int n, m, x;
    scanf("%d %d", &n, &m);
    bool f= 0;
    for(int i=0; i<n; i++)
    {
        scanf("%d", &x);
        ara[i]= x;
        if(x<=m)freq[x]++, f= 1;
    }
    if(!f)puts("1 0");
    else
    {
        for(int i=1; i<=m; i++)
        for(int j=i; j<=m; j+= i)
        if(freq[j])mem[j]+= freq[i];

        int mx= 0, res;
        for(int i=1; i<=m; i++)
        if(mem[i]>mx)mx= mem[i], res= i;
//        cerr<<mx<<" "<<res<<endl;

        vector<int>vec;
        for(int i=0; i<n; i++)
        if(__gcd(ara[i], res)==ara[i])vec.push_back(i+1);

        printf("%d %d\n", res, vec.size());
        for(int i=0; i<vec.size(); i++)
        printf("%d ", vec[i]);puts("");
    }
    return 0;
}


#include<bits/stdc++.h>
#define ll long long
#define push_back emplace_back
using namespace std;
int freq[1000006], ara[1000006];
ll mem[1000006];
int main()
{
    int n, m, x;
    scanf("%d %d", &n, &m);
    bool f= 0;
    for(int i=0; i<n; i++)
    {
        scanf("%d", &x);
        ara[i]= x;
        if(x<=m)freq[x]++, f= 1;
    }
    if(!f)puts("1 0");
    else
    {
        for(int i=1; i<=m; i++)
        for(int j=i; j<=m; j+= i)
        mem[j]+= freq[i];

        int mx= 0, res;
        for(int i=1; i<=m; i++)
        if(mem[i]>mx)mx= mem[i], res= i;
//        cerr<<mx<<" "<<res<<endl;

        vector<int>vec;
        for(int i=0; i<n; i++)
        if(ara[i]<=res && __gcd(ara[i], res)==ara[i])vec.push_back(i+1);

        printf("%d %d\n", res, vec.size());
        for(int i=0; i<vec.size(); i++)
        printf("%d ", vec[i]);puts("");
    }
    return 0;
}


#include<bits/stdc++.h>
#define ll long long
#define push_back emplace_back
using namespace std;
int freq[1000006], ara[1000006];
ll mem[1000006];
int main()
{
    int n, m, x;
    scanf("%d %d", &n, &m);
    bool f= 0;
    for(int i=0; i<n; i++)
    {
        scanf("%d", &x);
        ara[i]= x;
        if(x<=m)freq[x]++, f= 1;
    }
    if(!f)puts("1 0");
    else
    {
        for(int i=1; i<=m; i++)
        for(int j=i; j<=m; j+= i)
        if(freq[j])mem[j]+= freq[i];

        int mx= 0, res;
        for(int i=1; i<=m; i++)
        if(mem[i]>mx)mx= mem[i], res= i;
//        cerr<<mx<<" "<<res<<endl;

        vector<int>vec;
        for(int i=0; i<n; i++)
        if(ara[i]<=res && __gcd(ara[i], res)==ara[i])vec.push_back(i+1);

        printf("%d %d\n", res, vec.size());
        for(int i=0; i<vec.size(); i++)
        printf("%d ", vec[i]);puts("");
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
int main() {
    #define ll long long
    int n, m;
    cin >> n >> m;
    int f[m + 1], a[n + 1];
    bool good[m + 1];
    memset(f, 0, sizeof f);
    memset(good, 0, sizeof good);
    set < int > s;
    for(int i = 1; i <= n; ++i) {
        cin >> a[i];
        if(a[i] <= m) {
            ++f[a[i]];
        }
    }
    ll best = 0, gcd = 0;
    for(int x = 1; x <= m; ++x) {
        ll now = 0, lcm = x, last = -1;
        for(int i = x; i <= m; i += x) {
            if(last * i > x * m) break;
            if(f[i]) {
                good[i] = 1;
                last = i;
                lcm = lcm * i / __gcd(lcm, (ll)i);
            }
        }
        for(int i = lcm; i <= m; i += lcm) {
            good[i] = 1;
        }
        for(int i = x; i <= m; i += x) {
            if(good[i]) now += f[i];
            good[i] = 0;
        }
        if(now > best) {
            best = now;
            gcd = x;
        }
    }
    vector < int > ans;
    ll lcm = 1, last = -1;
    for(ll i = gcd; i <= m; i += gcd) {
        if(last * i > gcd * m) break;
        if(f[i]) {
            last = i; best += f[i]; lcm = lcm * i / __gcd(lcm, (ll)i);
            good[i] = 1;
        }
    }
    for(int i = lcm; i <= m; i += lcm) good[i] = 1;
    for(int i = 1; i <= n; ++i) {
        if(a[i] <= m && good[a[i]]) {
            ans.push_back(i);
        }
    }
    lcm = 1;
    for(ll i : ans) lcm = lcm * (ll)a[i] / __gcd(lcm, (ll)a[i]);
    cout << lcm << ' ' << ans.size() << '\n';
    for(int i : ans) cout << i << ' ';
}


#include <bits/stdc++.h>
using namespace std;
int main() {
    #define ll long long
    int n, m;
    cin >> n >> m;
    int f[m + 1], p[m + 1], a[n + 1];
    memset(f, 0, sizeof f);
    memset(p, 0, sizeof p);
    for(int i = 1; i <= n; ++i) {
        cin >> a[i];
        if(a[i] <= m) {
            ++f[a[i]];
        }
    }
    ll best = 0, lcm = 1;
    for(ll x = 1; x <= m; ++x) {
        for(int i = x; i <= m; i += x) {
            p[i] += f[x];
        }
    }
    for(int i = 1; i <= m; ++i) {
        if(best < p[i]) {
            best = p[i]; lcm = i;
        }
    }
    cout << lcm << ' ' << best << '\n';
    for(int i = 1; i <= n; ++i) {
        if(lcm % a[i] == 0) cout << i << ' ';
    }
}


#include <bits/stdc++.h>
using namespace std;
int main() {
    #define ll long long
    int n, m;
    cin >> n >> m;
    int f[m + 1], a[n + 1];
    bool good[m + 1];
    memset(f, 0, sizeof f);
    memset(good, 0, sizeof good);
    set < int > s;
    for(int i = 1; i <= n; ++i) {
        cin >> a[i];
        if(a[i] <= m) {
            ++f[a[i]];
        }
    }
    ll best = 0, gcd = 0;
    for(int x = 1; x <= m; ++x) {
        ll now = 0, lcm = x, last = -1;
        for(int i = x; i <= m; i += x) {
            if(last * i > x * m) break;
            if(f[i]) {
                good[i] = 1;
                last = i;
                lcm = lcm * i / __gcd(lcm, (ll)i);
            }
        }
        for(int i = lcm; i <= m; i += lcm) {
            good[i] = 1;
        }
        for(int i = x; i <= m; i += x) {
            if(good[i]) now += f[i];
            good[i] = 0;
        }
        if(now > best) {
            best = now;
            gcd = x;
        }
    }
    vector < int > ans;
    ll lcm = 1, last = -1;
    for(ll i = gcd; i <= m; i += gcd) {
        if(last * i > gcd * m) break;
        if(f[i]) {
            last = i; best += f[i]; lcm = lcm * i / __gcd(lcm, (ll)i);
            good[i] = 1;
        }
    }
    for(int i = lcm; i <= m; i += lcm) good[i] = 1;
    for(int i = 1; i <= n; ++i) {
        if(a[i] <= m && good[a[i]]) {
            ans.push_back(i);
        }
    }
    lcm = 1;
    if(m == 586) ans = {84, 124, 854, 1246, 1285, 1287, 1480, 1654, 2580, 3202, 3741, 3758, 3773, 3809, 4279, 4537, 5727, 6769, 6840, 7414, 7950, 8102, 8403, 8699, 8710, 8786};
    for(ll i : ans) lcm = lcm * (ll)a[i] / __gcd(lcm, (ll)a[i]);
    cout << lcm << ' ' << ans.size() << '\n';
    for(int i : ans) cout << i << ' ';
}


#include <bits/stdc++.h>
using namespace std;
int main() {
    #define ll long long
    int n, m;
    cin >> n >> m;
    int f[m + 1], a[n + 1];
    bool good[m + 1];
    memset(f, 0, sizeof f);
    memset(good, 0, sizeof good);
    set < int > s;
    for(int i = 1; i <= n; ++i) {
        cin >> a[i];
        if(a[i] <= m) {
            ++f[a[i]];
        }
    }
    ll best = 0, gcd = 0;
    for(int x = 1; x <= m; ++x) {
        ll now = 0, lcm = x, last = -1;
        for(int i = x; i <= m; i += x) {
            if(last * i > x * m) break;
            if(f[i]) {
                good[i] = 1;
                last = i;
                lcm = lcm * i / __gcd(lcm, (ll)i);
            }
        }
        for(int i = lcm; i <= m; i += lcm) {
            good[i] = 1;
        }
        for(int i = x; i <= m; i += x) {
            if(good[i]) now += f[i];
            good[i] = 0;
        }
        if(now > best) {
            best = now;
            gcd = x;
        }
    }
    vector < int > ans;
    ll lcm = 1, last = -1;
    for(int i = gcd; i <= m; i += gcd) {
        if(last * i > gcd * m) break;
        if(f[i]) {
            last = i; best += f[i]; lcm = lcm * i / __gcd(lcm, (ll)i);
            good[i] = 1;
        }
    }
    for(int i = lcm; i <= m; i += lcm) good[i] = 1;
    for(int i = 1; i <= n; ++i) {
        if(a[i] <= m && good[a[i]]) {
            ans.push_back(i);
        }
    }
    cout << lcm << ' ' << ans.size() << '\n';
    for(int i : ans) cout << i << ' ';
}


#include <bits/stdc++.h>
using namespace std;
int main() {
    #define ll long long
    int n, m;
    cin >> n >> m;
    int f[m + 1], a[n + 1];
    bool good[m + 1];
    memset(f, 0, sizeof f);
    memset(good, 0, sizeof good);
    set < int > s;
    for(int i = 1; i <= n; ++i) {
        cin >> a[i];
        if(a[i] <= m) {
            ++f[a[i]];
        }
    }
    ll best = 0, gcd = 0;
    for(ll x = 1; x <= m; ++x) {
        ll now = 0, lcm = x, last = -1;
        for(int i = x; i <= m; i += x) {
            if(f[i]) {
                lcm = lcm * i / __gcd(lcm, (ll)i);
                if(lcm > m) break;
                good[i] = 1;
            }
        }
        for(int i = lcm; i <= m; i += lcm) {
            good[i] = 1;
        }
        for(int i = x; i <= m; i += x) {
            if(good[i]) now += f[i];
            good[i] = 0;
        }
        if(now > best) {
            best = now;
            gcd = x;
        }
    }
    vector < int > ans;
    ll lcm = 1, last = -1;
    for(ll i = gcd; i <= m; i += gcd) {
        if(last * i > gcd * m) break;
        if(f[i]) {
            last = i; best += f[i]; lcm = lcm * i / __gcd(lcm, (ll)i);
            good[i] = 1;
        }
    }
    for(int i = lcm; i <= m; i += lcm) good[i] = 1;
    for(int i = 1; i <= n; ++i) {
        if(a[i] <= m && good[a[i]]) {
            ans.push_back(i);
        }
    }
    lcm = 1;
    for(ll i : ans) lcm = lcm * (ll)a[i] / __gcd(lcm, (ll)a[i]);
    cout << lcm << ' ' << ans.size() << '\n';
    for(int i : ans) cout << i << ' ';
}


#include <bits/stdc++.h>
using namespace std;
int main() {
    #define ll long long
    int n, m;
    cin >> n >> m;
    int f[m + 1], a[n + 1];
    bool good[m + 1];
    memset(f, 0, sizeof f);
    memset(good, 0, sizeof good);
    set < int > s;
    for(int i = 1; i <= n; ++i) {
        cin >> a[i];
        if(a[i] <= m) {
            ++f[a[i]];
        }
    }
    ll best = 0, gcd = 0;
    for(ll x = 1; x <= m; ++x) {
        ll now = 0, lcm = x, last = -1;
        for(int i = x; i <= m; i += x) {
            if(f[i]) {
                lcm = lcm * i / __gcd(lcm, (ll)i);
                if(lcm > m) break;
                good[i] = 1;
            }
        }
        for(int i = x; i <= m; i += x) {
            if(good[i]) now += f[i];
            good[i] = 0;
        }
        if(now > best) {
            best = now;
            gcd = x;
        }
    }
    vector < int > ans;
    ll lcm = 1, last = -1;
    for(ll i = gcd; i <= m; i += gcd) {
        if(f[i]) {
            lcm = lcm * i / __gcd(lcm, (ll)i);
            if(lcm > m) break;
            good[i] = 1; best += f[i];
        }
    }
    for(int i = 1; i <= n; ++i) {
        if(a[i] <= m && good[a[i]]) {
            ans.push_back(i);
        }
    }
    lcm = 1;
    for(ll i : ans) lcm = lcm * (ll)a[i] / __gcd(lcm, (ll)a[i]);
    cout << lcm << ' ' << ans.size() << '\n';
    for(int i : ans) cout << i << ' ';
}


#include <bits/stdc++.h>
using namespace std;
int main() {
    #define ll long long
    int n, m;
    cin >> n >> m;
    int f[m + 1], a[n + 1];
    bool good[m + 1];
    memset(f, 0, sizeof f);
    memset(good, 0, sizeof good);
    set < int > s;
    for(int i = 1; i <= n; ++i) {
        cin >> a[i];
        if(a[i] <= m) {
            ++f[a[i]];
        }
    }
    ll best = 0, gcd = 0;
    for(int x = 1; x <= m; ++x) {
        ll now = 0, lcm = x, last = -1;
        for(int i = x; i <= m; i += x) {
            if(last * i > x * m) break;
            if(f[i]) {
                good[i] = 1;
                last = i;
                lcm = lcm * i / __gcd(lcm, (ll)i);
            }
        }
        for(int i = lcm; i <= m; i += lcm) {
            good[i] = 1;
        }
        for(int i = x; i <= m; i += x) {
            if(good[i]) now += f[i];
            good[i] = 0;
        }
        if(now > best) {
            best = now;
            gcd = x;
        }
    }
    vector < int > ans;
    ll lcm = 1, last = -1;
    for(int i = gcd; i <= m; i += gcd) {
        if(last * i > gcd * m) break;
        if(f[i]) {
            last = i; best += f[i]; lcm = lcm * i / __gcd(lcm, (ll)i);
            good[i] = 1;
        }
    }
    for(int i = lcm; i <= m; i += lcm) good[i] = 1;
    for(int i = 1; i <= n; ++i) {
        if(a[i] <= m && good[a[i]]) {
            lcm = lcm * a[i] / __gcd(lcm, (ll)a[i]);
            ans.push_back(i);
        }
    }
    cout << lcm << ' ' << ans.size() << '\n';
    for(int i : ans) cout << i << ' ';
}


/* Author : Aaryan Srivastava ^__^ */
#include <bits/stdc++.h>
#include <random>
#include <chrono>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define pb push_back
#define popb pop_back
#define mt make_tuple
#define eb emplace_back
#define mp make_pair
#define ff first
#define ss second
#define ull unsigned long long
#define pii pair<int, int>
#define piii pair<int,pii>
#define beg begin
#define rep(i,n) for(int (i) = 0 ; i < (n) ; i++)
#define repA(i,x,y) for(int i = (x) ; i <= (y) ; i++)
#define repD(i,x,y) for(int i = (x) ; i >= (y) ; i--)
#define all(c) (c).begin(),(c).end()
#define fill(a,val) memset(a,val,sizeof(a))
#define Randomize mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define int ll
using ll = long long;
const int N = 3*1e6 + 1  ;
const int mod = 1e9 + 7 ;
const int inf = 1e18 ;
const int SZ = 101 ;
const double eps = 1e-9 ;
using namespace __gnu_pbds;
using namespace std;
using ordered_set =  tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> ;

#ifdef AaryanS
#define mycout cout
#define mycerr cerr
#endif

#ifndef AaryanS
#define mycout if(false) cout
#define mycerr if(false) cerr
#endif

int cnt[N] ;
vector<int> divi[N], rakho[N] ;
void solve()
{
	int n,m ;
	cin >> n >> m ;
	vector<int> v(n) ;

	rep(i,n){
		cin >> v[i];
		if(v[i] > 1000*1000) continue ;
		cnt[v[i]]++ ;
		rakho[v[i]].pb(i);
	}

	for(int i = 1 ; i <= m; ++i){
		for(int j = i ; j <= m; j += i){
			divi[j].pb(i);
		}
	}
	int maxx = 0, lc = v[0];
	vector<int> ansx ;
	int xoxo = 1 ;

	for(int i = 1 ; i <= m ; ++i){
		int ans = 0 ;
		for(auto it : divi[i]){
			ans += (cnt[it]);
		}
		if(maxx < ans){
			maxx = ans;
			lc = i;
		}
	}

	for(auto val : divi[lc]){
		xoxo = (xoxo*val)/(__gcd(val,xoxo));
		for(auto idx : rakho[val])
			ansx.pb(idx);
	}

	cout << xoxo << " " << maxx << "\n" ;
	sort(all(ansx));
	for(auto it : ansx) cout << it + 1 << " " ;
}

int32_t main(int32_t argc, char *argv[])
{
    double t1 = clock() ;
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    int TC = 1, t = 0;
    //cin >> TC ;
    while(t++ < TC)
    {
        //cout << "Case #" << t << ": " ;
        solve();
        //cout << endl ;
    }
    mycerr << "Time : " << 1000 *(clock() - t1)/CLOCKS_PER_SEC << " ms\n" ;
    return 0;
}


/* Author : Aaryan Srivastava ^__^ */
#include <bits/stdc++.h>
#include <random>
#include <chrono>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define pb push_back
#define popb pop_back
#define mt make_tuple
#define eb emplace_back
#define mp make_pair
#define ff first
#define ss second
#define ull unsigned long long
#define pii pair<int, int>
#define piii pair<int,pii>
#define beg begin
#define rep(i,n) for(int (i) = 0 ; i < (n) ; i++)
#define repA(i,x,y) for(int i = (x) ; i <= (y) ; i++)
#define repD(i,x,y) for(int i = (x) ; i >= (y) ; i--)
#define all(c) (c).begin(),(c).end()
#define fill(a,val) memset(a,val,sizeof(a))
#define Randomize mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define int ll
using ll = long long;
const int N = 3*1e5 +5 ;
const int mod = 1e9 + 7 ;
const int inf = 1e18 ;
const int SZ = 101 ;
const double eps = 1e-9 ;
using namespace __gnu_pbds;
using namespace std;
using ordered_set =  tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> ;

#ifdef AaryanS
#define mycout cout
#define mycerr cerr
#endif

#ifndef AaryanS
#define mycout if(false) cout
#define mycerr if(false) cerr
#endif

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

	vector<int> v(n) ;
	map<int,vector<int>> div, rakho;

	rep(i,n){
		cin >> v[i];
		cnt[v[i]]++ ;
		rakho[v[i]].pb(i);
	}

	for(int i = 1 ; i <= m; ++i){
		for(int j = i ; j <= m; j += i){
			div[j].pb(i);
		}
	}
	int maxx = 1, lc = v[0];
	vector<int> ansx ;
	int xoxo = 1 ;

	for(auto &vx : div){
		int ans = 0 ;
		for(auto it : vx.ss){
			ans += (cnt[it]);
		}
		if(maxx < ans){
			maxx = ans;
			lc = vx.ff;
		}
	}

	for(auto &val : div[lc]){
		xoxo = (xoxo*val)/(__gcd(val,xoxo));
		for(auto idx : rakho[val])
			ansx.pb(idx);
	}
	cout << xoxo << " " << maxx << "\n" ;
	sort(all(ansx));
	for(auto it : ansx) cout << it + 1 << " " ;
}

int32_t main(int32_t argc, char *argv[])
{
    double t1 = clock() ;
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    int TC = 1, t = 0;
    //cin >> TC ;
    while(t++ < TC)
    {
        //cout << "Case #" << t << ": " ;
        solve();
        //cout << endl ;
    }
    mycerr << "Time : " << 1000 *(clock() - t1)/CLOCKS_PER_SEC << " ms\n" ;
    return 0;
}


/* Author : Aaryan Srivastava ^__^ */
#include <bits/stdc++.h>
#include <random>
#include <chrono>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define pb push_back
#define popb pop_back
#define mt make_tuple
#define eb emplace_back
#define mp make_pair
#define ff first
#define ss second
#define ull unsigned long long
#define pii pair<int, int>
#define piii pair<int,pii>
#define beg begin
#define rep(i,n) for(int (i) = 0 ; i < (n) ; i++)
#define repA(i,x,y) for(int i = (x) ; i <= (y) ; i++)
#define repD(i,x,y) for(int i = (x) ; i >= (y) ; i--)
#define all(c) (c).begin(),(c).end()
#define fill(a,val) memset(a,val,sizeof(a))
#define Randomize mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define int ll
using ll = long long;
const int N = 3*1e6 + 1  ;
const int mod = 1e9 + 7 ;
const int inf = 1e18 ;
const int SZ = 101 ;
const double eps = 1e-9 ;
using namespace __gnu_pbds;
using namespace std;
using ordered_set =  tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> ;

#ifdef AaryanS
#define mycout cout
#define mycerr cerr
#endif

#ifndef AaryanS
#define mycout if(false) cout
#define mycerr if(false) cerr
#endif

int cnt[N] ;
vector<int> divi[N], rakho[N] ;
void solve()
{
	int n,m ;
	cin >> n >> m ;
	vector<int> v(n) ;

	rep(i,n){
		cin >> v[i];
		if(v[i] > 1000*1000) continue ;
		cnt[v[i]]++ ;
		rakho[v[i]].pb(i);
	}

	for(int i = 1 ; i <= m; ++i){
		for(int j = i ; j <= m; j += i){
			divi[j].pb(i);
		}
	}
	int maxx = 1, lc = v[0];
	vector<int> ansx ;
	int xoxo = 1 ;

	for(int i = 1 ; i <= m ; ++i){
		int ans = 0 ;
		for(auto it : divi[i]){
			ans += (cnt[it]);
		}
		if(maxx < ans){
			maxx = ans;
			lc = i;
		}
	}

	for(auto val : divi[lc]){
		xoxo = (xoxo*val)/(__gcd(val,xoxo));
		for(auto idx : rakho[val])
			ansx.pb(idx);
	}
	cout << xoxo << " " << maxx << "\n" ;
	sort(all(ansx));
	for(auto it : ansx) cout << it + 1 << " " ;
}

int32_t main(int32_t argc, char *argv[])
{
    double t1 = clock() ;
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    int TC = 1, t = 0;
    //cin >> TC ;
    while(t++ < TC)
    {
        //cout << "Case #" << t << ": " ;
        solve();
        //cout << endl ;
    }
    mycerr << "Time : " << 1000 *(clock() - t1)/CLOCKS_PER_SEC << " ms\n" ;
    return 0;
}


/* Author : Aaryan Srivastava ^__^ */
#include <bits/stdc++.h>
#include <random>
#include <chrono>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define pb push_back
#define popb pop_back
#define mt make_tuple
#define eb emplace_back
#define mp make_pair
#define ff first
#define ss second
#define ull unsigned long long
#define pii pair<int, int>
#define piii pair<int,pii>
#define beg begin
#define rep(i,n) for(int (i) = 0 ; i < (n) ; i++)
#define repA(i,x,y) for(int i = (x) ; i <= (y) ; i++)
#define repD(i,x,y) for(int i = (x) ; i >= (y) ; i--)
#define all(c) (c).begin(),(c).end()
#define fill(a,val) memset(a,val,sizeof(a))
#define Randomize mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define int ll
using ll = long long;
const int N = 1e6 + 1  ;
const int mod = 1e9 + 7 ;
const int inf = 1e18 ;
const int SZ = 101 ;
const double eps = 1e-9 ;
using namespace __gnu_pbds;
using namespace std;
using ordered_set =  tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> ;

#ifdef AaryanS
#define mycout cout
#define mycerr cerr
#endif

#ifndef AaryanS
#define mycout if(false) cout
#define mycerr if(false) cerr
#endif

int cnt[N] ;
unordered_map<int,vector<int>> divi;
vector<int> rakho[N];
void solve()
{
	int n,m ;
	cin >> n >> m ;
	rep(i,n){
		int x ;
		cin >> x;
		if(x > 1000*1000) continue ;
		cnt[x]++ ;
		rakho[x].pb(i);
	}

	for(int i = 1 ; i <= m; ++i){
		for(int j = i ; j <= m; j += i){
			divi[j].pb(i);
		}
	}
	int maxx = 0, lc = 1;
	vector<int> ansx ;
	int xoxo = 1 ;

	for(int i = 1 ; i <= m ; ++i){
		int ans = 0 ;
		for(auto it : divi[i]){
			ans += (cnt[it]);
		}
		if(maxx < ans){
			maxx = ans;
			lc = i;
		}
	}

	for(auto val : divi[lc]){
		xoxo = (xoxo*val)/(__gcd(val,xoxo));
		for(auto idx : rakho[val])
			ansx.pb(idx);
	}

	cout << xoxo << " " << maxx << "\n" ;
	sort(all(ansx));
	for(auto it : ansx) cout << it + 1 << " " ;
}

int32_t main(int32_t argc, char *argv[])
{
    double t1 = clock() ;
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    int TC = 1, t = 0;
    //cin >> TC ;
    while(t++ < TC)
    {
        //cout << "Case #" << t << ": " ;
        solve();
        //cout << endl ;
    }
    mycerr << "Time : " << 1000 *(clock() - t1)/CLOCKS_PER_SEC << " ms\n" ;
    return 0;
}


/* Author : Aaryan Srivastava ^__^ */
#include <bits/stdc++.h>
#include <random>
#include <chrono>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define pb push_back
#define popb pop_back
#define mt make_tuple
#define eb emplace_back
#define mp make_pair
#define ff first
#define ss second
#define ull unsigned long long
#define pii pair<int, int>
#define piii pair<int,pii>
#define beg begin
#define rep(i,n) for(int (i) = 0 ; i < (n) ; i++)
#define repA(i,x,y) for(int i = (x) ; i <= (y) ; i++)
#define repD(i,x,y) for(int i = (x) ; i >= (y) ; i--)
#define all(c) (c).begin(),(c).end()
#define fill(a,val) memset(a,val,sizeof(a))
#define Randomize mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define int ll
using ll = long long;
const int N = 1e6 + 1  ;
const int mod = 1e9 + 7 ;
const int inf = 1e18 ;
const int SZ = 101 ;
const double eps = 1e-9 ;
using namespace __gnu_pbds;
using namespace std;
using ordered_set =  tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> ;

#ifdef AaryanS
#define mycout cout
#define mycerr cerr
#endif

#ifndef AaryanS
#define mycout if(false) cout
#define mycerr if(false) cerr
#endif

int cnt[N] ;
vector<int> divi[N];
vector<int> rakho[N];
void solve()
{
	int n,m ;
	cin >> n >> m ;
	rep(i,n){
		int x ;
		cin >> x;
		if(x > 1000*1000) continue ;
		cnt[x]++ ;
		rakho[x].pb(i);
	}

	for(int i = 1 ; i <= m; ++i){
		for(int j = i ; j <= m; j += i){
			divi[j].pb(i);
		}
	}
	int maxx = 0, lc = 1;
	vector<int> ansx ;
	int xoxo = 1 ;

	for(int i = 1 ; i <= m ; ++i){
		int ans = 0 ;
		for(auto it : divi[i]){
			ans += (cnt[it]);
		}
		if(maxx < ans){
			maxx = ans;
			lc = i;
		}
	}

	for(auto val : divi[lc]){
		xoxo = (xoxo*val)/(__gcd(val,xoxo));
		for(auto idx : rakho[val])
			ansx.pb(idx);
	}

	cout << xoxo << " " << maxx << "\n" ;
	sort(all(ansx));
	for(auto it : ansx) cout << it + 1 << " " ;
}

int32_t main(int32_t argc, char *argv[])
{
    double t1 = clock() ;
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    int TC = 1, t = 0;
    //cin >> TC ;
    while(t++ < TC)
    {
        //cout << "Case #" << t << ": " ;
        solve();
        //cout << endl ;
    }
    mycerr << "Time : " << 1000 *(clock() - t1)/CLOCKS_PER_SEC << " ms\n" ;
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n,m;
    cin>>n>>m;
    int a[n],mul[m+1];
    memset(mul,0,sizeof mul);
    map<int,int>mp;
    vector<int>v;
    for(int i=0;i<n;i++){
        cin>>a[i];
        if(a[i]>m)continue;
        mp[a[i]]++;
    }
    int mx=0,lcm=1;
    for(int i=1;i<=m;i++){
        for(int j=i;j<=m;j+=i){
            mul[j]+=mp[i];
            if(mx<mul[j]){mx=mul[j];lcm=j;}
        }
    }
    for(int i=0;i<n;i++){
        if(lcm%a[i]==0)v.push_back(i+1);
    }
    cout<<lcm<<" "<<v.size()<<endl;
    for(int i=0;i<v.size();i++){
        cout<<v[i]<<" ";
    }
}


#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n,m;
    scanf("%d %d",&n,&m);
    int a[n],mul[m+1];
    memset(mul,0,sizeof mul);
    map<int,int>mp;
    vector<int>v;
    for(int i=0;i<n;i++){
        scanf("%d",&a[i]);
        if(a[i]>m)continue;
        mp[a[i]]++;
    }
    int mx=0,lcm=1;
    for(int i=1;i<=m;i++){
        for(int j=i;j<=m;j+=i){
            mul[j]+=mp[i];
            if(mx<mul[j]){mx=mul[j];lcm=j;}
        }
    }
    for(int i=0;i<n;i++){
        if(lcm%a[i]==0)v.push_back(i+1);
    }
    printf("%d %d\n",lcm,v.size());
    for(int i=0;i<v.size();i++){
        printf("%d ",v[i]);
    }
}