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

int func(int a,int b,int& ans_x,int& ans_y){
	if(b == 0){ //再帰の一番最後にたどり着いた場合
		ans_x = 1;
		ans_y = 0;
		return a; //最小公倍数
	}else{
		int ret = func(b,(a%b),ans_y,ans_x);
		ans_y -= (a/b)*ans_x;
		return ret;
	}
}

int main(){

	int A,B,ans_x,ans_y;

	scanf("%d %d",&A,&B);

	func(A,B,ans_x,ans_y);

	printf("%d %d\n",ans_x,ans_y);

	return 0;
}

/*
#define NUM 100005

struct GROUP{
	vector<int> nodes;
};

struct Edge{
	Edge(int arg_to,bool arg_is_directed){
		to = arg_to;
		is_directed = arg_is_directed;
	}
	int to;
	bool is_directed;
};

struct Info{
	Info(int arg_node_id,int arg_adj_node){
		node_id = arg_node_id;
		adj_node = arg_adj_node;
	}
	int node_id,adj_node;
};

struct Data{
	Data(){
		node_id = 0;
		sum_cost = 0;
	}
	Data(int arg_node_id,ll arg_sum_cost){
		node_id = arg_node_id;
		sum_cost = arg_sum_cost;
	}
	bool operator<(const struct Data &arg) const{
		return sum_cost < arg.sum_cost; //★総コストの降順(PQ)★
	}

	int node_id;
	ll sum_cost;
};

int V,E;
GROUP group[NUM]; //強連結成分のグループ
vector<Edge> G[NUM];
vector<int> DAG_G[NUM];
vector<int> rev_G[NUM];
vector<Info> Connect[NUM];
stack<int> S;
bool check[NUM];
int table[NUM],in_num[NUM];
int group_index;
ll max_node_cost[NUM],depth[NUM],in_max[NUM];
bool is_in[NUM],searched[NUM],is_leaf[NUM];


void dfs(int node_id){
	check[node_id] = true;

	for(int i = 0; i < G[node_id].size(); i++){
		if(!check[G[node_id][i].to])dfs(G[node_id][i].to);
	}
	S.push(node_id);
}

void reverse_dfs(int node_id){
	check[node_id] = true;

	group[group_index].nodes.push_back(node_id); //group[group_index]にノードを突っ込む
	table[node_id] = group_index;

	for(int i = 0; i < rev_G[node_id].size(); i++){
		if(!check[rev_G[node_id][i]])reverse_dfs(rev_G[node_id][i]);
	}
}

void makeTree(int node_id,int group_id,int value){

	depth[node_id] = value;
	int next_node;

	for(int i = 0; i < G[node_id].size(); i++){
		next_node = G[node_id][i].to;
		//別グループか、または訪問済ならcontinue(木なので、各ノードを訪れる回数は1回であるはず)
		if(table[next_node] != group_id || depth[next_node] != BIG_NUM)continue;

		makeTree(next_node,group_id,value+1);
		is_leaf[node_id] = false; //子がいれば葉ではない
	}
}

//子から親に情報を伝える
void dfs_to_root(int node_id,int group_id,ll sum_cost){

	max_node_cost[node_id] = max(max_node_cost[node_id],sum_cost);

	for(int k = 0; k < G[node_id].size(); k++){
		//別グループ、または同グループかつ子孫方向のノードならSKIP
		if(table[G[node_id][k].to] != group_id || depth[G[node_id][k].to] >= depth[node_id])continue;

		dfs_to_root(G[node_id][k].to,group_id,sum_cost+1);
	}
}

//親から子へ情報を伝える
void dfs_to_descendant(int node_id,int group_id,ll sum_cost){

	max_node_cost[node_id] = max(max_node_cost[node_id],sum_cost);

	ll tmp_cost;
	priority_queue<Data> Q;

	for(int i = 0; i < G[node_id].size(); i++){ //★子の、入次エッジ由来のコストを走査★
		//別グループ、または同グループかつ親方向のノードならSKIP
		if(table[G[node_id][i].to] != group_id || depth[G[node_id][i].to] <= depth[node_id] || searched[G[node_id][i].to] == true)continue;
		if(max_node_cost[G[node_id][i].to] == -1)continue;

		searched[G[node_id][i].to] = true; //★★★多重辺あり★★★

		Q.push(Data(G[node_id][i].to,max_node_cost[G[node_id][i].to]+1));	//★親(node_id)へ渡る+1
	}

	if(Q.size() == 0){ //値を持つ子の数が0

		if(is_in[node_id]){
			tmp_cost = in_max[node_id]+1;
			for(int i = 0; i < G[node_id].size(); i++){
				if(table[G[node_id][i].to] != group_id || depth[G[node_id][i].to] <= depth[node_id])continue; //別グループは不可
				dfs_to_descendant(G[node_id][i].to,group_id,tmp_cost);
			}
		}else{
			//とりあえず投げる
			for(int i = 0; i < G[node_id].size(); i++){
				if(table[G[node_id][i].to] != group_id || depth[G[node_id][i].to] <= depth[node_id])continue; //別グループは不可
				dfs_to_descendant(G[node_id][i].to,group_id,-BIG_NUM);
			}
		}

	}else if(Q.size() == 1){

		Data data1 = Q.top();

		if(is_in[node_id]){
			tmp_cost = in_max[node_id]+1;
		}else{
			tmp_cost = -BIG_NUM;
		}

		for(int i = 0; i < G[node_id].size(); i++){

			if(table[G[node_id][i].to] != group_id || depth[G[node_id][i].to] <= depth[node_id])continue;

			if(G[node_id][i].to == data1.node_id){ //ボトムアップで最大値をもたらした辺方向の場合

				dfs_to_descendant(G[node_id][i].to,group_id,tmp_cost); //★子へ下る1

			}else{

				dfs_to_descendant(G[node_id][i].to,group_id,max(tmp_cost,data1.sum_cost+1));
			}

		}


	}else{ //子の数が2以上

		if(is_in[node_id]){
			tmp_cost = in_max[node_id]+1;
		}else{
			tmp_cost = -BIG_NUM;
		}

		Data data1 = Q.top();
		Q.pop();
		Data data2 = Q.top();
		Q.pop();

		for(int i = 0; i < G[node_id].size(); i++){

			if(table[G[node_id][i].to] != group_id || depth[G[node_id][i].to] <= depth[node_id])continue;

			if(G[node_id][i].to == data1.node_id){ //ボトムアップで最大値をもたらした辺方向の場合

				dfs_to_descendant(G[node_id][i].to,group_id,max(tmp_cost,data2.sum_cost+1));//★子へ下る1

			}else{

				dfs_to_descendant(G[node_id][i].to,group_id,max(tmp_cost,data1.sum_cost+1));//★子へ下る1
			}

		}
	}
}

void calc_cost(int group_id){

	makeTree(group[group_id].nodes[0],group_id,0);
	int tmp_node;
	ll tmp_cost;

	bool is_root_in = false;
	ll max_root_in = 0;

	int in_count = 0;


	他のSCC成分とつながっているノード(DAGにおける入次エッジ)があれば、
	 * そのコスト情報を親に伝える
	 *
	for(int i = 0; i < Connect[group_id].size(); i++){

		if(max_node_cost[Connect[group_id][i].adj_node] == -1){
			continue;
		}
		in_count++;

		tmp_node = Connect[group_id][i].node_id;
		tmp_cost = max_node_cost[Connect[group_id][i].adj_node];

		max_node_cost[tmp_node] = max(max_node_cost[tmp_node],tmp_cost+1); //★★★★

		if(tmp_node == group[group_id].nodes[0]){ //★★★★ルートノードにも入次がある場合★★★★
			is_root_in = true;
			max_root_in = max(max_root_in,tmp_cost+1);
		}

		is_in[tmp_node] = true;
		in_max[tmp_node] = max(in_max[tmp_node],tmp_cost+1); //★入次する中での最大コスト★

		for(int k = 0; k < G[tmp_node].size(); k++){
			//別グループ、または同グループかつ子孫方向のノードならSKIP
			if(table[G[tmp_node][k].to] != group_id || depth[G[tmp_node][k].to] >= depth[tmp_node])continue;
			dfs_to_root(G[tmp_node][k].to,group_id,tmp_cost+2); //★★tmp_nodeに下る+1,tmp_nodeから上る+1
		}
	}

	if(in_count == 0){ //DAGの始点

		is_root_in = true;
		max_root_in = 0;

		//各ノードにコスト0の入次があったとする[親方向に伝える]
		for(int i = 0; i < group[group_id].nodes.size(); i++){

			tmp_node = group[group_id].nodes[i];
			tmp_cost = 0;
			max_node_cost[tmp_node] = max(max_node_cost[tmp_node],(ll)0);
			is_in[tmp_node] = true;
			in_max[tmp_node] = 0;


			if(!is_leaf[tmp_node]){ //葉だけdfs_to_rootすれば良い
				continue;
			}
			for(int k = 0; k < G[tmp_node].size(); k++){
				//別グループ、または同グループかつ子孫方向のノードならSKIP
				if(table[G[tmp_node][k].to] != group_id || depth[G[tmp_node][k].to] >= depth[tmp_node])continue;
				dfs_to_root(G[tmp_node][k].to,group_id,tmp_cost+1); //★★+1であることに注意★★
			}
		}
	}

	★SCC内のルートノードから、親方向経路の最大値を伝える
	 * 各ノードにおいて、ある子へ値を伝える場合に、その子以外の子の最大値を伝える
	 * ★★★ルートノードに入次がある場合は注意★★★
	 * あるノードが「子」として走査される回数は1回であるため、オーダはO(N)であるはず★

	tmp_node = group[group_id].nodes[0];
	priority_queue<Data> Q;

	for(int i = 0; i < G[tmp_node].size(); i++){ //★子の、入次エッジ由来のコストを走査★

		if(table[G[tmp_node][i].to] != group_id || depth[G[tmp_node][i].to] <= depth[tmp_node] || searched[G[tmp_node][i].to] == true)continue;
		if(max_node_cost[G[tmp_node][i].to] == -1)continue;

		searched[G[tmp_node][i].to] = true; //★★★多重辺あり★★★

		Q.push(Data(G[tmp_node][i].to,max_node_cost[G[tmp_node][i].to]+1));	//★親(node_id)へ渡る+1
	}

	if(Q.size() == 0){ //値を持つ子の数が0

		if(is_root_in){
			tmp_cost = max_root_in+1;
			for(int i = 0; i < G[tmp_node].size(); i++){
				if(table[G[tmp_node][i].to] != group_id || depth[G[tmp_node][i].to] <= depth[tmp_node])continue; //別グループは不可
				dfs_to_descendant(G[tmp_node][i].to,group_id,tmp_cost);
			}
		}else{
			//とりあえず投げる
			for(int i = 0; i < G[tmp_node].size(); i++){
				if(table[G[tmp_node][i].to] != group_id || depth[G[tmp_node][i].to] <= depth[tmp_node])continue; //別グループは不可
				dfs_to_descendant(G[tmp_node][i].to,group_id,-BIG_NUM);
			}
		}

	}else if(Q.size() == 1){

		Data data1 = Q.top();

		if(is_root_in){
			tmp_cost = max_root_in+1;
		}else{
			tmp_cost = -BIG_NUM;
		}

		for(int i = 0; i < G[tmp_node].size(); i++){

			if(table[G[tmp_node][i].to] != group_id || depth[G[tmp_node][i].to] <= depth[tmp_node])continue;

			if(G[tmp_node][i].to == data1.node_id){ //ボトムアップで最大値をもたらした辺方向の場合

				dfs_to_descendant(G[tmp_node][i].to,group_id,tmp_cost); //★子へ下る1

			}else{

				dfs_to_descendant(G[tmp_node][i].to,group_id,max(tmp_cost,data1.sum_cost+1)); //★子へ下る1
			}
		}


	}else{ //子の数が2以上

		if(is_root_in){
			tmp_cost = max_root_in+1;
		}else{
			tmp_cost = -BIG_NUM;
		}

		Data data1 = Q.top();
		Q.pop();
		Data data2 = Q.top();
		Q.pop();

		for(int i = 0; i < G[tmp_node].size(); i++){

			if(table[G[tmp_node][i].to] != group_id || depth[G[tmp_node][i].to] <= depth[tmp_node])continue;

			if(G[tmp_node][i].to == data1.node_id){ //ボトムアップで最大値をもたらした辺方向の場合

				dfs_to_descendant(G[tmp_node][i].to,group_id,max(tmp_cost,data2.sum_cost+1));//★子へ下る1

			}else{

				dfs_to_descendant(G[tmp_node][i].to,group_id,max(tmp_cost,data1.sum_cost+1));//★子へ下る1
			}

		}
	}
}

int main(){

	scanf("%d %d",&V,&E);
	int from,to,command;

	for(int loop = 0; loop < E; loop++){

		scanf("%d %d %d",&from,&to,&command);
		from--;
		to--;
		if(command == 1){ //有向

			G[from].push_back(Edge(to,true));
			rev_G[to].push_back(from);

		}else{

			G[from].push_back(Edge(to,false));
			G[to].push_back(Edge(from,false));
			rev_G[from].push_back(to);
			rev_G[to].push_back(from);
		}
	}

	★SCC分解する★
	for(int i = 0; i < V; i++)check[i] = false;

	for(int i = 0; i < V; i++){
		if(!check[i]){
			dfs(i);
		}
	}

	for(int i = 0; i < V; i++)check[i] = false;

	//★強連結成分ごとに、ノードをまとめる
	group_index = 0;
	while(!S.empty()){
		if(!check[S.top()]){
			reverse_dfs(S.top());
			group_index++;
		}
		S.pop();
	}

	★SCC単位のDAGにおける有向エッジを求める
	 * ついでに、閉路がないか調べる(SCC内エッジ数 >= SCC内ノード数なら閉路あり)★
	int node_num,edge_num;
	int tmp_node,next_group;

	printf("group_index:%d\n",group_index);

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

		node_num = (int)group[i].nodes.size();
		edge_num = 0;

		for(int k = 0; k < group[i].nodes.size(); k++){

			tmp_node = group[i].nodes[k];
			//あるノードから伸びるエッジを調べる
			for(int p = 0; p < G[tmp_node].size(); p++){

				next_group = table[G[tmp_node][p].to];
				if(next_group == i){

					if(G[tmp_node][p].is_directed){ //★SCC内に有向辺があったら、閉路あり★
						printf("Infinite\n");
						return 0;
					}
					edge_num++;

				}else{
					DAG_G[i].push_back(next_group);
				}
			}
		}

		edge_num /= 2; //無向edgeは2倍に計上されるはず
		//printf("edge_num:%d node_num:%d\n",edge_num,node_num);
		if(edge_num >= node_num){
			printf("Infinite\n");
			return 0;
		}

		for(int k = 0; k < group[i].nodes.size(); k++){

			tmp_node = group[i].nodes[k];
			//★★入次辺を探す
			for(int p = 0; p < rev_G[tmp_node].size(); p++){

				next_group = table[rev_G[tmp_node][p]];
				if(next_group == i){
					//Do nothing
				}else{
					//debug++;
					Connect[i].push_back(Info(tmp_node,rev_G[tmp_node][p])); //★入次辺を記録★
				}
			}
		}
	}

	★SCC-DAGにおける入次数を求める★
	for(int i = 0; i < group_index; i++)in_num[i] = 0;



	for(int i = 0; i < group_index; i++){
		sort(DAG_G[i].begin(),DAG_G[i].end());
		DAG_G[i].erase(unique(DAG_G[i].begin(),DAG_G[i].end()),DAG_G[i].end());
		for(int k = 0; k < DAG_G[i].size(); k++){
			in_num[DAG_G[i][k]]++;
		}
	}

	int dijk[NUM];
	for(int k = 0; k < group_index; k++)dijk[k] = BIG_NUM;
	queue<int> DE;
	for(int i = 0; i < group_index; i++){
		if(in_num[i] == 0){
			dijk[i] = 0;
			DE.push(i);
		}
	}

	while(!DE.empty()){

		for(int i = 0; i < DAG_G[DE.front()].size(); i++){
			if(dijk[DAG_G[DE.front()][i]] > dijk[DE.front()]+1){
				dijk[DAG_G[DE.front()][i]] = dijk[DE.front()]+1;
				DE.push(DAG_G[DE.front()][i]);
			}
		}
		DE.pop();
	}

	int shishi = 0;
	for(int i = 0; i < group_index; i++){
		shishi = max(shishi,dijk[i]);
	}
	printf("shishi:%d\n",shishi);
	return 0;

	for(int i = 0; i < V; i++){
		max_node_cost[i] = -1;
		depth[i] = BIG_NUM;
		is_in[i] = false;
		in_max[i] = 0;
		searched[i] = false;
		is_leaf[i] = true;
	}

	queue<int> Q;


	//★★各グループをトポロジカル順に処理する★★
	for(int i = 0; i < group_index; i++){
		if(in_num[i] == 0){
			Q.push(i);
		}
	}

	//printf("shishi debug;%d\n",debug);

	int tmp_group;

	int debug = 0;

	while(!Q.empty()){

		tmp_group = Q.front();
		Q.pop();

		calc_cost(tmp_group);

		debug++;
		//if(debug == 20)break;

		//出次先のグループの入次数を減らす
		for(int i = 0; i < DAG_G[tmp_group].size(); i++){
			in_num[DAG_G[tmp_group][i]] -= 1;
			if(in_num[DAG_G[tmp_group][i]] == 0){
				Q.push(DAG_G[tmp_group][i]);
			}
		}
	}

	ll ans = 0;
	for(int i = 0; i < V; i++){
		ans = max(ans,max_node_cost[i]);
	}

	printf("%lld\n",ans);

	return 0;
}
*/



Measured memory_bytes: 3232