#include <iostream>
#include<vector>
#include<map>
#include <unordered_map>
#include<algorithm>
#include <string>
#include <sstream>
#include <set>
#include <queue>
#include <map>
#include <fstream>
#include <iomanip>
#include <cstdlib>
#include <bitset>
#include <stack>
#include <math.h>

#include <stdlib.h>
#include <time.h>
#include <stdio.h>

#define en "\n"

using namespace std;
namespace patch
{
	template < typename T > std::string to_string(const T& n)
	{
		std::ostringstream stm;
		stm << n;
		return stm.str();
	}
}

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;

const ld PI = 3.14159265358979323846;
ll mdf = 1e+9 + 7;
ld eps = 1e-12;

const ll INF = 3e18 + 1337;

int A = 4;

struct Matrix {
	vector<vector<ll>> mx = vector<vector<ll>>(A, vector<ll>(A, 0)); // max 2^32, min 0

	Matrix operator *(const Matrix& other)
	{
		Matrix temp;

		for (int i = 0; i < A; i++)
			for (int j = 0; j < A; j++)
				for (int k = 0; k < A; k++)
					temp.mx[i][j] += mx[i][k] * other.mx[k][j];

		for (int i = 0; i < A; i++)
			for (int j = 0; j < A; j++)
				temp.mx[i][j] %= mdf;

		return temp;
	};
};

Matrix exp_matrix(Matrix a, int k)
{
	Matrix temp;
	for (int i = 0; i < A; i++)
		temp.mx[i][i] = 1;

	while (k)
	{
		if (k % 2)
			temp = temp * a;

		a = a * a;
		k /= 2;
	}
	return temp;
}

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

bool isAPrime(long long m)
{
	for (long long p = 2; p * p <= m; p++)
	{
		if (m % p == 0) { return false; }
	}
	return true;
}

long long binpow(long long a, long long n) {
	if (n == 0)
		return 1;
	if (n % 2 == 1)
		return (binpow(a, n - 1) * a) % mdf;
	else {
		long long b = binpow(a, n / 2) % mdf;
		return (b * b) % mdf;
	}
}

ll fact[100005];

ll C(int n, int k) {
	return fact[n] * binpow(fact[k], mdf - 2) % mdf * binpow(fact[n - k], mdf - 2) % mdf;
}

int count_setbits(int N)
{
	int cnt = 0;

	while (N > 0)
	{
		cnt += (N & 1);
		N = N >> 1;
	}

	return cnt;

}

ll phi(ll n) { //функция эйлера, вычисляет кол-во чисел взаимнопростых c n
	ll result = n;
	for (ll i = 2; i * i <= n; ++i)
		if (n % i == 0) {
			while (n % i == 0)
				n /= i;
			result -= result / i;
		}
	if (n > 1)
		result -= result / n;
	return result;
}


bool compare(pair<int, ll> a, pair<int, ll> b)
{
	return a.second < b.second;
}

int mergethem(vector<int>& a, int l, int m, int r)
{
	int Inv = 0;

	vector<int> buff(r - l + 1);
	int pos1 = l, pos2 = m + 1, posB = 0;

	while (pos1 <= m && pos2 <= r)
	{
		if (a[pos1] < a[pos2])
		{
			buff[posB++] = a[pos1++];
		}
		else
		{
			Inv += m - pos1 + 1;
			buff[posB++] = a[pos2++];
		}
	}

	while (pos1 <= m)
		buff[posB++] = a[pos1++];

	while (pos2 <= r)
		buff[posB++] = a[pos2++];

	copy(buff.begin(), buff.end(), a.begin() + l);

	return Inv;
}

int mergesort(vector<int>& a, int l, int r)
{
	int curInv = 0;
	if (l == r)
		return curInv;

	int m = (l + r) / 2;

	curInv += mergesort(a, l, m);
	curInv += mergesort(a, m + 1, r);

	curInv += mergethem(a, l, m, r);

	return curInv;
}

int sz[1];
int p[1];

int get(int v)
{
	if (p[v] != v)
		p[v] = get(p[v]);
	return p[v];
}

void union_sets(int a, int b)
{
	a = get(a);
	b = get(b);

	if (a == b) return;

	if (sz[a] > sz[b]) // a < b
		swap(a, b);

	p[a] = b;
	sz[b] += sz[a];
}

void solve(int t) {
	//freopen("input.txt", "r", stdin);
	//freopen("bomb.out", "w", stdout);

	int s; cin >> s;

	ll ans = 0;

	for (int i = 1; i <= s; i++)
	{
		int ss = s - i * 3;

		if (ss < 0) break;
		//cout << ss + i - 1 << " " << ss << ": " << C(ss + i - 1, ss) << en;
		ans += C(ss + i - 1, ss);
		ans %= mdf;
	}
	cout << ans << en;
}


int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	fact[0] = 1;
	for (int i = 1; i < 100005; i++)
		fact[i] = fact[i - 1] * i % mdf;

	int q = 1;
	//cin >> q;
	int i = 0;
	while (q--) solve(++i);

	return 0;
}

Measured memory_bytes: 4424