#include <cstdio>
#include <cmath>
#include <cfloat>
#include <cstring>
#include <cassert>
#include <vector>
#include <algorithm>
using namespace std;

/* double extention Library. */

const double EPS = 1e-8;

bool eq(double a, double b)
{
	return (fabs(a - b) <= EPS);
}

bool lt(double a, double b)
{
	return (a - b < EPS);
}

bool leq(double a, double b)
{
	return (lt(a, b) || eq(a, b));
}

bool gt(double a, double b)
{
	return (a - b > EPS);
}

bool geq(double a, double b)
{
	return (gt(a, b) || eq(a, b));
}

/* 2-D Geometry Library. */

class Point{
public:
	double x, y;
	Point (double x = 0, double y = 0): x(x), y(y){}
	Point operator + (Point p){
		return (Point(x + p.x, y + p.y));
	}
	Point operator - (Point p){
		return (Point(x - p.x, y - p.y));
	}
	Point operator * (double a){
		return (Point(x * a, y * a));
	}
	double abs(){
		return (sqrt(norm()));
	}
	double norm(){
		return (x * x + y * y);
	}
	bool operator < (const Point &p) const {
		return (x != p.x ? x < p.x : y < p.y);
	}
	bool operator == (const Point &p) const {
		return (fabs(x - p.x) < EPS && fabs(y - p.y) < EPS);
	}
};

typedef Point Vector;
typedef vector<Point> Polygon;

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

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

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

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

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

int ccw(Point p0, Point p1, Point p2){
	Vector a = p1 - p0;
	Vector b = p2 - p0;
	if (cross(a, b) > EPS)  return (COUNTER_CLOCKWISE);
	if (cross(a, b) < -EPS) return (CLOCKWISE);
	if (dot(a, b) < -EPS)   return (ONLINE_BACK);
	if (norm(a) < norm(b))  return (ONLINE_FRONT);
	return (ON_SEGMENT);
}

bool isIntersect(Point p1, Point p2, Point p3, Point p4){
	return (ccw(p1, p2, p3) * ccw(p1, p2, p4) <= 0 &&
			ccw(p3, p4, p1) * ccw(p3, p4, p2) <= 0 );
}



bool isInside(Polygon gon, Point p)
{
	for (int i = 0; i < gon.size(); i++){
		if (ccw(gon[i], gon[(i + 1) % gon.size()], p) == CLOCKWISE) return (false);
	}
	return (true);
}

Point unitVector(Vector t)
{
	double u = abs(t);
	return (Point(t.x / u , t.y / u));
}

double getCos(Vector a, Vector b)
{
	return (dot(a, b) / (abs(a) * abs(b)));
}

double getSin(Point a , Point b)
{
	double t = getCos(a, b);
	return (sqrt(1.0 - t * t));
}

double getDistPL(Point p, Point a, Point b)
{
	return (fabs(cross(b - a, p - a)) / abs(b - a));
}

double getDistPS(Point p, Point a, Point b)
{
	if(dot(b - a, p - a) < EPS) return (abs(p - a));
	if(dot(a - b, p - b) < EPS) return (abs(p - b));
	return (getDistPL(p, a, b));
}

Point interPointS(Point a1 , Point a2 , Point b1 , Point b2)
{
	Point b = b2 - b1;
	double d1 = fabs(cross(b, a1 - b1));
	double d2 = fabs(cross(b, a2 - b1));
	double t = d1 / (d1 + d2);
	Point a = a2 - a1;
	Point v = a * t;
	return (a1 + v);
}

Point interPointL(Point a1 , Point a2 , Point b1 , Point b2)
{
	Point a = a2-a1;
	Point b = b2-b1;
	double t = cross(b, b1 - a1) / cross(b, a);
	Point v = a * t;
	return (a1 + v);
}

void interPointLC(Point a , Point b , Point c , double r , Point ans[])
{
	if (getDistPL(c, a, b) > r + EPS) return;
	Point v = unitVector(b - a);
	double delta = dot(v, a - c) * dot(v, a - c) - abs(a - c) * abs(a - c) + r * r;
	double t = -dot(v, a - c);
	double s = sqrt(delta);
	ans[0] = a + v * (t + s);
	ans[1] = a + v * (t - s);
}

Point xTranslate(Point t,double k)
{
	return Point(t.x , 2*k-t.y);
}

Point yTranslate(Point t,double k)
{
	return Point(2*k-t.x , t.y);
}

Point oTranslate(Point t, Point k)
{
	return k + (k-t);
}

Point rotate(Point t , Point p , double r)
{
	double ta=cos(r)*(t.x-p.x)-sin(r)*(t.y-p.y)+p.x;
	double tb=sin(r)*(t.x-p.x)+cos(r)*(t.y-p.y)+p.y;
	return Point(ta , tb);
}

void interPointCC(Point a , double ra , Point b , double rb , Point ans[])
{
	double di=fabs(abs(a-b));
	if(di > ra+rb || di < fabs(ra-rb)) return;
	double t=(ra*ra-rb*rb+di*di)/(di+di);
	double rd=acos(t/ra);

	Point dv=unitVector(b-a);
	Point g1=rotate(dv , Point(0,0) , rd);
	Point g2=rotate(dv , Point(0,0) , -rd);
	ans[0]=a+g1*ra;
	ans[1]=a+g2*ra;
}

Point normalVector(Point p,Point a,Point b)
{
	Point v=unitVector(b-a);
	v = cross(v , p-a) > 0 ?  Point(v.y,(-1)*v.x) : Point((-1)*v.y , v.x);
	return v*getDistPL(p,a,b);
}

Point fTranslate(Point t , Point a , Point b)
{
	return t+normalVector(t,a,b)*2;
}

double area(Point a, Point b, Point c){
	return fabs(cross(c-a , b-a)*0.5);
}

double polygonArea(Polygon t){
	double ans = 0.0;
	for (unsigned int i = 0; i < t.size(); i++)
		ans += cross(t[i] , t[(i + 1) % t.size()]);
	return (ans / 2);
}

Polygon conhel(Polygon& ps)
{
    sort(ps.begin(), ps.end());
    int k = 0, n = static_cast<int>(ps.size());
    Polygon qs(n * 2);
    
    for (int i = 0; i < n; i++){
      while (k > 1 && cross(qs[k - 1] - qs[k - 2], ps[i] - qs[k - 1]) < EPS) k--;
      qs[k++] = ps[i];
    }

    for (int i = n - 2, t = k; i >= 0; i--){
      while (k > t && cross(qs[k - 1] - qs[k - 2], ps[i] - qs[k - 1]) < EPS) k--;
      qs[k++] = ps[i];
    }

    qs.resize(k - 1);
    return (qs);
}

void Coch(int n, Point l, Point r)
{
	if (n == 0){
		printf("%lf %lf\n", r.x, r.y);
		return;
	}
	
	Point m1, m2;
	
	m1 = (l * 2 + r) * (1 / 3.0);
	m2 = (l + r * 2) * (1 / 3.0);
	
	double len = abs(m2 - m1);
	
	Point m3 = rotate(m2 - m1, Point(0, 0), M_PI / 2);
	
	m3 = (m1 + m2) * 0.5 + unitVector(m3) * (len * sqrt(3) / 2);
	
	Coch(n - 1, l, m1);
	Coch(n - 1, m1, m3);
	Coch(n - 1, m3, m2);
	Coch(n - 1, m2, r);
}

int main()
{
	int n;
	
	scanf("%d", &n);
	
	printf("%lf %lf\n", 0.0, 0.0);
	
	Coch(n, Point(0, 0), Point(100, 0));
}

Measured memory_bytes: 1076