#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
typedef pair<int,P> P1;
typedef pair<P,P> P2;
#define pu push
#define pb push_back
#define mp make_pair
#define eps 1e-7
#define INF 1000000000
#define fi first
#define sc second
#define rep(i,x) for(int i=0;i<x;i++)
#define repn(i,x) for(int i=1;i<=x;i++)
#define SORT(x) sort(x.begin(),x.end())
#define ERASE(x) x.erase(unique(x.begin(),x.end()),x.end())
#define POSL(x,v) (lower_bound(x.begin(),x.end(),v)-x.begin())
#define POSU(x,v) (upper_bound(x.begin(),x.end(),v)-x.begin())
const int mod = 1000000007;
struct fft{
	struct compleX{
		double real,imag;
		compleX(){
		    real = imag = 0.;
		}
		compleX(double a,double b){
		    real = a; imag = b;
		}
		inline compleX operator +(const compleX &x) const { return {real+x.real, imag+x.imag}; }
		inline compleX operator -(const compleX &x) const { return {real-x.real, imag-x.imag}; }
		inline compleX operator *(const compleX &x) const { return {real*x.real-imag*x.imag, real*x.imag+imag*x.real}; }
		inline compleX operator *(const double  &y) const { return {real*y, imag*y}; }
	};
    compleX conj(const compleX &a) { return {a.real, -a.imag}; }
	const int MOD = 1000000007;
	const double PI = acos(-1);
	typedef compleX Complex;

	//Nは畳み込んだ後のサイズ以上
	const int N = (1<<18), L = 15, MASK = (1 << L) - 1;
	vector<Complex>w[20];
	void FFTInit() {
	    w[18].resize(N);
		for (int i = 0; i < N; ++i) {
			w[18][i] = Complex(cos(2 * i * PI / N), sin(2 * i * PI / N));
		}
		for(int i=17;i>=0;i--){
		    w[i].resize((1<<i));
		    for(int j=0;j<(1<<i);j++){
		        w[i][j] = w[i+1][j<<1];
		    }
		}
	}
	void FFT(vector<Complex>&p, int n) {
		for (int i = 1, j = 0; i < n - 1; ++i) {
			for (int s = n; j ^= s >>= 1, ~j & s;);
			if (i < j) {
				swap(p[i], p[j]);
			}
		}
	//	int bg = __lg(n);
		for (int d = 0; (1 << d) < n; ++d) {
			int m = 1 << d, m2 = m * 2, rm = n >> (d + 1);
			for (int i = 0; i < n; i += m2) {
				for (int j = 0; j < m; ++j) {
					Complex &p1 = p[i + j + m], &p2 = p[i + j];
					Complex t = w[d+1][j] * p1;
					p1 = p2 - t;
					p2 = p2 + t;
				}
			}
		}
	}
    vector<int> mod_mul(vector<int>a,vector<int>b){
        int NN = 1;
        while(NN < a.size()+b.size()) NN <<= 1;
        vector<Complex>A(NN), B(NN), C(NN), D(NN);
    	for (int i = 0; i < NN; ++i) {
    		if(i < a.size()){
    			A[i] = Complex(a[i] >> L, a[i] & MASK);
    		}
    		else{
    			A[i] = Complex(0.0, 0.0);
    		}
    		if(i < b.size()){
    			B[i] = Complex(b[i] >> L, b[i] & MASK);
    		}
    		else{
    			B[i] = Complex(0.0, 0.0);
    		}
    	}
    	FFT(A, NN); FFT(B, NN);
    	for (int i = 0; i < NN; ++i) {
    		int j = (NN - i) % NN;
    		Complex da = (A[i] - conj(A[j])) * Complex(0, -0.5),
    				db = (A[i] + conj(A[j])) * Complex(0.5, 0),
    				dc = (B[i] - conj(B[j])) * Complex(0, -0.5),
    				dd = (B[i] + conj(B[j])) * Complex(0.5, 0);
    		C[j] = da * dd + da * dc * Complex(0, 1);
    		D[j] = db * dd + db * dc * Complex(0, 1);
    	}
    	FFT(C, NN); FFT(D, NN);
    	a.resize(NN);
    	for (int i = 0; i < NN; ++i) {
    		long long da = (long long)(C[i].imag / NN + 0.5) % MOD,
    				  db = (long long)(C[i].real / NN + 0.5) % MOD,
    				  dc = (long long)(D[i].imag / NN + 0.5) % MOD,
    				  dd = (long long)(D[i].real / NN + 0.5) % MOD;
    		a[i] = ((dd << (L * 2)) + ((db + dc) << L) + da) % MOD;
    	}
    	return a;
    }
}kaede;

ll modpow(ll x,ll n){
	ll res=1;
	while(n>0){
		if(n&1) res=res*x%mod;
		x=x*x%mod;
		n>>=1;
	}
	return res;
}

namespace power_series_master {
    //x^iの係数をvecc[i]にもつものとする
    //各々の処理はmod x^Mをサポートするものとする
    
    //add,sub,diff,intg,mul_int,mul,inv,sqrt,log,exp
    //add subでミスってたら流石に引退
    //diff,intgも流石に大丈夫だと思うけど、diffに定数を噛ませて0を返す仕様で変なハマり方をしないか心配
    //一番怖いのはlogで、手元でexpと組み合わせてテストしたら大丈夫そうだったけど、GP peterhof H でverifyしたいよね
    //mod は998244353固定なので、他の素数だった場合はmulをarbitrary_mod_convに変えないといけない
    
    //verify list
    
    //mul_int,sub,sqrt,inv... CF 438E
    //exp... yosupo judge
    #define vi vector<int>
    vi init(vi a, int x){
    	a.resize(x,0);
    	return a;
    }
    vi add(vi a, vi b,int M=-1){
        if(a.size() < b.size()) swap(a,b);
        for(int i=0;i<b.size();i++){
            a[i]+=b[i];
            if(a[i] < 0) a[i] += mod;
            if(a[i] >= mod) a[i] -= mod;
        }
        if(M >= 0 && a.size() > M) a.resize(M);
        return a;
    }
    vi sub(vi a, vi b,int M=-1){
        if(a.size() < b.size()) a.resize(b.size(),0);
        for(int i=0;i<b.size();i++){
            a[i]-=b[i];
            if(a[i] < 0) a[i] += mod;
            if(a[i] >= mod) a[i] -= mod;
        }
        if(M >= 0 && a.size() > M) a.resize(M);
        return a;
    }
    //微分
    vi diff(vi a,int M=-1){
    	reverse(a.begin(),a.end());
    	a.pop_back();
    	reverse(a.begin(),a.end());
    	for(int i=0;i<a.size();i++) a[i] = 1LL*a[i]*(i+1)%mod;
    	if(M >= 0 && a.size() > M) a.resize(M);
    	if(a.empty()) a.pb(0);
    	return a;
    }
    //積分、定数項は指定可能
    vi intg(vi a,int coef=0,int M=-1){
    	reverse(a.begin(),a.end());
    	a.push_back(coef);
    	reverse(a.begin(),a.end());
    	for(int i=1;i<a.size();i++) a[i] = 1LL*a[i]*modpow(i,mod-2)%mod;
    	if(M >= 0 && a.size() > M) a.resize(M);
    	return a;
    }
    vi mul_int(vi a,int x,int M=-1){
        for(int i=0;i<a.size();i++){
            ll A = 1LL*a[i]*x%mod;
            if(A < 0) A += mod;
            a[i] = A;
        }
        if(M >= 0 && a.size() > M) a.resize(M);
        return a;
    }
    vi mul(vi a,vi b,int M=-1){
        //modが99...のときはnttできる
        //任意modの場合は、適当に区切ってもいいしgarnerしてもいいし任せます
		a = kaede.mod_mul(a,b);
		if(M >= 0 && a.size() > M) a.resize(M);
        return a;
    }
    //vecで表される多項式の-1乗、x^(M-1)の項までを求めてM長のvectorを返す
    //ただし、vec[0] = 0の場合は無理
    //r1(z)f(z) = x*? + 1
    //rn(z)f(z) = x^n*? + 1とする
    //r(2n)(z) = 2*rn(z)-rn(z)^2f(z)とすればOK!
    vi inv(vi a,int M){
        if(a.empty() || a[0] == 0) return vi();
        //1の場合をやっておく
        vi r[30];
        r[0].pb(modpow(a[0],mod-2));
        int cur = 1;
        int nxt = 1;
        vi vec3;
        while(cur < M){
        	int nw = min(cur*2,(int)(a.size()));
        	int sz = vec3.size();
        	vec3.resize(nw,0);
        	for(int t=sz;t<nw;t++){
        		vec3[t] = a[t];
        	}
            r[nxt] = sub(mul_int(r[nxt-1],2),mul(mul(r[nxt-1],r[nxt-1]),vec3));
            r[nxt].resize(r[nxt-1].size()*2);
            nxt++;
            cur *= 2;
        }
        assert(r[nxt-1].size() >= M);
        r[nxt-1].resize(M);
        assert(r[nxt-1].size() == M);
        return r[nxt-1];
    }
    //vecで表される多項式の平方根、x^(M-1)の項までを求めてM長のvectorを返す
    //ただし、vec[0] = 0の場合は無理
    //整数の平方根求めるのかったるいのでそれはまた後日
    //s1(z)^2 = f(z) (mod z)
    //sn(z)^2 = f(z) (mod z^n) とする
    //s(2n)(z) = 1/2 * (sn(z)+f(z)*sn(z)^-1)
    vi sqrt(vi a,int M){
        if(a.empty() || a[0] == 0) return vi();
        //1の場合をやっておく
        vi s[30];
        //今日はvec[0] = 1のことしか考えません
        s[0].pb(1);
        assert(1LL*s[0][0]*s[0][0]%mod == a[0]);
        int cur = 1;
        int nxt = 1;
        vi vec3;
        while(cur < M){
            int nw = min(cur*2,(int)(a.size()));
        	int sz = vec3.size();
        	vec3.resize(nw,0);
        	for(int t=sz;t<nw;t++){
        		vec3[t] = a[t];
        	}
            s[nxt] = add(s[nxt-1],mul(vec3,inv(s[nxt-1],cur*2)));
            s[nxt] = mul_int(s[nxt],modpow(2,mod-2));
            s[nxt].resize(cur*2);
            nxt++;
            cur *= 2;
        }
        s[nxt-1].resize(M);
        assert(s[nxt-1].size() == M);
        return s[nxt-1];
    }
    //vecで表される多項式のlog()、x^(M-1)の項までを求めてM長のvectorを返す
    //ただし、vec[0] = 0の場合は無理
    //log(f(x)) = intg(f'(x)/f(x)) = intg(mul(diff(f(x),need+1),inv(f(x),need+1),need+1))
    //積分定数は0固定なので、vec[0]!=1のものを噛ませた場合は壊れる
    vi log(vi a,int M){
        if(a.empty() || a[0] == 0) return vi();
        vi x = diff(a,M);
        vi y = inv(a,M);
        vi z = mul(x,y,M);
        return intg(z,0,M);
    }
    //vecで表される多項式のexp()、x^(M-1)の項までを求めてM長のvectorを返す
    //ただし、vec[0] != 0の場合は無理
    //exp(a)の定数項は必ず1なので、定数項!=1の多項式のlogを噛ませた場合は壊れる
    //http://www.csd.uwo.ca/~eschost/publications/BoSc09-final.pdf
    vi exp(vi a,int M){
        if(a.empty() || a[0] != 0) return vi();
        vi f={1},g={1},q,aa;
        int m = 1;
        vi h = diff(a);
        while(m<=M){
			g = sub(mul_int(g,2,m),mul(mul(f,g,m),g,m),m);
			while(aa.size() < 2*m){
			    if(aa.size() >= a.size()) aa.pb(0);
			    else aa.pb(a[aa.size()]);
			}
			if(m>1){
				vi w = add(q,mul(g,sub(diff(f,2*m-1),mul(f,q,2*m-1),2*m-1),2*m-1),2*m-1);
				f = add(f,mul(f,sub(aa,intg(w,0,2*m),2*m),2*m),2*m);
			}
			else{
				vi w = mul(g,diff(f,2*m-1),2*m-1);
				f = add(f,mul(f,sub(aa,intg(w,0,2*m),2*m),2*m),2*m);
			}
			m*=2;
			while(q.size() < m-1){
				if(q.size() >= h.size()) q.pb(0);
				else q.pb(h[q.size()]);
			}
		}
		f.resize(M);
		assert(f.size() == M);
		return f;
    }
};

//ここから
int n;
vector<int>one,two;
int main(){
    kaede.FFTInit();
	cin >> n;
	one.pb(0); two.pb(0);
	for(int i=1;i<=n;i++){
		one.pb(1); two.pb(i);
	}
	auto O = power_series_master::exp(one,n+5);
	auto T = power_series_master::exp(two,n+5);
	ll ans = 1LL*T[n] - modpow(1LL*O[n],2);
	cout << (ans%mod+mod)%mod << endl;
}


Measured memory_bytes: 39824