import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.NoSuchElementException;

public class Main {
    public static void main(String[] args) {
        PrintWriter out = new PrintWriter(System.out);
        FastScanner sc = new FastScanner();
        StringBuilder sb = new StringBuilder();
        int N = sc.nextInt();
        long[] A = new long[N];
        long[] B = new long[N];
        boolean isEven = true;
        for(int i=0; i<N; i++) {
           A[i] = sc.nextLong();
            if (isEven) {
                B[0] += A[i];
                isEven = false;
            } else {
                B[0] -= A[i];
                isEven = true;
            }
        }
        sb.append(B[0]);
        sb.append(" ");
        for(int i=1; i<N; i++) {
            B[i] = 2*A[i-1]-B[i-1];
            sb.append(B[i]);
            sb.append(" ");
        }
        out.println(sb.toString());
        out.flush();
    }
}

class FastScanner {
    private final InputStream in = System.in;
    private final byte[] buffer = new byte[1024];
    private int ptr = 0;
    private int buflen = 0;
    private boolean hasNextByte() {
        if (ptr < buflen) {
            return true;
        }else{
            ptr = 0;
            try {
                buflen = in.read(buffer);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (buflen <= 0) {
                return false;
            }
        }
        return true;
    }
    private int readByte() { if (hasNextByte()) return buffer[ptr++]; else return -1;}
    private static boolean isPrintableChar(int c) { return 33 <= c && c <= 126;}
    public boolean hasNext() { while(hasNextByte() && !isPrintableChar(buffer[ptr])) ptr++; return hasNextByte();}
    public String next() {
        if (!hasNext()) throw new NoSuchElementException();
        StringBuilder sb = new StringBuilder();
        int b = readByte();
        while(isPrintableChar(b)) {
            sb.appendCodePoint(b);
            b = readByte();
        }
        return sb.toString();
    }
    public long nextLong() {
        if (!hasNext()) throw new NoSuchElementException();
        long n = 0;
        boolean minus = false;
        int b = readByte();
        if (b == '-') {
            minus = true;
            b = readByte();
        }
        if (b < '0' || '9' < b) {
            throw new NumberFormatException();
        }
        while(true){
            if ('0' <= b && b <= '9') {
                n *= 10;
                n += b - '0';
            }else if(b == -1 || !isPrintableChar(b)){
                return minus ? -n : n;
            }else{
                throw new NumberFormatException();
            }
            b = readByte();
        }
    }
    public int nextInt() {
        long nl = nextLong();
        if (nl < Integer.MIN_VALUE || nl > Integer.MAX_VALUE) throw new NumberFormatException();
        return (int) nl;
    }
    public double nextDouble() { return Double.parseDouble(next());}
}


import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.Set;

public class Main {

	public static void main(String[] args){
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();

		int[] a = new int[n];
		long[] b = new long[n+1];
		for( int i=0 ; i<n ; i++ ) {
			a[i] = sc.nextInt();
		}

		long sum = 0;
		for( int i=0 ; i<n ; i++ ) {
			sum += a[i];
		}
		long sum2 = a[1];
		for( int i=3 ; i<n-1 ; i++ ) {
			sum2 += a[i];
		}
		b[0]= sum - 2*sum2;
		for( int i=0 ; i<n ; i++ ) {
			b[i+1] = a[i]*2 - b[i];
			System.out.println(b[i]);
		}
	}
}


import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.Set;

public class Main {

	public static void main(String[] args){
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();

		int[] a = new int[n];
		int[] b = new int[n+1];
		for( int i=0 ; i<n ; i++ ) {
			a[i] = sc.nextInt();
		}

		for( int i=0 ; i<n ; i++ ) {
			b[i+1] = a[i]*2 - b[i];
		}
		b[0]=b[n]/2;
		for( int i=0 ; i<n ; i++ ) {
			b[i+1] = a[i]*2 - b[i];
			System.out.println(b[i]);
		}
	}
}


import java.util.*; import java.io.*; import java.math.*;
public class Main{
	//Don't have to see. start------------------------------------------
	static class InputIterator{
		ArrayList<String> inputLine = new ArrayList<String>(1024);
		int index = 0; int max; String read;
		InputIterator(){
			BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
			try{
				while((read = br.readLine()) != null){
					inputLine.add(read);
				}
			}catch(IOException e){}
			max = inputLine.size();
		}
		boolean hasNext(){return (index < max);}
		String next(){
			if(hasNext()){
				return inputLine.get(index++);
			}else{
				throw new IndexOutOfBoundsException("There is no more input");
			}
		}
	}
	static HashMap<Integer, String> CONVSTR = new HashMap<Integer, String>();
	static InputIterator ii = new InputIterator();//This class cannot be used in reactive problem.
	static PrintWriter out = new PrintWriter(System.out);
	static void flush(){out.flush();}
	static void myout(Object t){out.println(t);}
	static void myerr(Object t){System.err.print("debug:");System.err.println(t);}
	static String next(){return ii.next();}
	static boolean hasNext(){return ii.hasNext();}
	static int nextInt(){return Integer.parseInt(next());}
	static long nextLong(){return Long.parseLong(next());}
	static double nextDouble(){return Double.parseDouble(next());}
	static ArrayList<String> nextStrArray(){return myconv(next(), 8);}
	static ArrayList<String> nextCharArray(){return myconv(next(), 0);}
	static ArrayList<Integer> nextIntArray(){
		ArrayList<String> input = nextStrArray(); ArrayList<Integer> ret = new ArrayList<Integer>(input.size());
		for(int i = 0; i < input.size(); i++){
			ret.add(Integer.parseInt(input.get(i)));
		}
		return ret;
	}
	static ArrayList<Long> nextLongArray(){
		ArrayList<String> input = nextStrArray(); ArrayList<Long> ret = new ArrayList<Long>(input.size());
		for(int i = 0; i < input.size(); i++){
			ret.add(Long.parseLong(input.get(i)));
		}
		return ret;
	}
	static String myconv(Object list, int no){//only join
		String joinString = CONVSTR.get(no);
		if(list instanceof String[]){
			return String.join(joinString, (String[])list);
		}else if(list instanceof ArrayList){
			return String.join(joinString, (ArrayList)list);
		}else{
			throw new ClassCastException("Don't join");
		}
	}
	static ArrayList<String> myconv(String str, int no){//only split
		String splitString = CONVSTR.get(no);
		return new ArrayList<String>(Arrays.asList(str.split(splitString)));
	}
	public static void main(String[] args){
		CONVSTR.put(8, " "); CONVSTR.put(9, "\n"); CONVSTR.put(0, "");
		solve();flush();
	}
	//Don't have to see. end------------------------------------------
	static void solve(){//Here is the main function
		int N = nextInt();
		ArrayList<Integer> list = nextIntArray();
		int sum = 0;
		for(int i = 0; i < N; i++){
			if(i % 2 == 0){
				sum += list.get(i) * 2;
			}else{
				sum -= list.get(i) * 2;
			}
		}
		int[] output = new int[N];
		output[0] = sum / 2;
		for(int i = 1; i < N; i++){
			output[i] = list.get(i - 1) * 2 - output[i - 1];
		}
		String[] print = new String[N];
		for(int i = 0; i < N; i++){
			print[i] = String.valueOf(output[i]);
		}
		myout(myconv(print,8));
	}
	//Method addition frame start

	//Method addition frame end
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i, n) for(int i = 0; i < (n); i++)
#define rep1(i, n) for(int i = 1; i <= (n); i++)
#define co(x) cout << (x) << "\n"
#define cosp(x) cout << (x) << " "
#define ce(x) cerr << (x) << "\n"
#define cesp(x) cerr << (x) << " "
#define pb push_back
#define mp make_pair
#define Would
#define you
#define please

const int cm = 1 << 17;
char cn[cm], * ci = cn + cm, ct;
inline char getcha() {
	if (ci - cn == cm) { fread_unlocked(cn, 1, cm, stdin); ci = cn; }
	return *ci++;
}
inline int getint() {
	int A = 0;
	if (ci - cn + 16 > cm) while ((ct = getcha()) >= '0') A = A * 10 + ct - '0';
	else while ((ct = *ci++) >= '0') A = A * 10 + ct - '0';
	return A;
}

const int dm = 1 << 20;
char dn[dm], *di = dn, dt;
inline void putint(int X) {
	if (X == 0) {
		*di++ = '0';
		*di++ = ' ';
		return;
	}
	int keta = 0;
	char C[10];
	while (X) {
		*(C + keta) = '0' + X % 10;
		X /= 10;
		keta++;
	}
	for (int i = keta - 1; i >= 0; i--) *di++ = (*(C + i));
	*di++ = ' ';
}

int main() {
	cin.tie(0);
	ios::sync_with_stdio(false);

	int N = getint();
	int A[100000];
	ll ans = (A[0] = getint());

	rep1(i, N - 1) {
		A[i] = getint();
		if (i & 1) ans = ans - A[i];
		else ans = ans + A[i];
	}

	putint(ans);
	rep(i, N - 1) {
		putint((ans = 2 * A[i] - ans));
	}

	fwrite_unlocked(dn, di - dn, 1, stdout);

	Would you please return 0;
}


#include<bits/stdc++.h>
using namespace std;
inline void rd(int &x){
  int k, m=0;
  x=0;
  for(;;){
    k = getchar_unlocked();
    if(k=='-'){
      m=1;
      break;
    }
    if('0'<=k&&k<='9'){
      x=k-'0';
      break;
    }
  }
  for(;;){
    k = getchar_unlocked();
    if(k<'0'||k>'9'){
      break;
    }
    x=x*10+k-'0';
  }
  if(m){
    x=-x;
  }
}
inline void wt_L(char a){
  putchar_unlocked(a);
}
inline void wt_L(int x){
  char f[10];
  int m=0, s=0;
  if(x<0){
    m=1;
    x=-x;
  }
  while(x){
    f[s++]=x%10;
    x/=10;
  }
  if(!s){
    f[s++]=0;
  }
  if(m){
    putchar_unlocked('-');
  }
  while(s--){
    putchar_unlocked(f[s]+'0');
  }
}
int N;
int A[100000];
int res[100000];
int main(){
  int i, x;
  rd(N);
  {
    int Lj4PdHRW;
    for(Lj4PdHRW=0;Lj4PdHRW<N;Lj4PdHRW++){
      rd(A[Lj4PdHRW]);
    }
  }
  for(i=1;i<N;i++){
    res[i] = A[i-1] - res[i-1];
  }
  x = (A[N-1] - res[N-1]) / 2;
  for(i=0;i<N;i++){
    if(i%2==0){
      res[i]+=x;
    }
    else{
      res[i]-=x;
    }
  }
  {
    int KL2GvlyY;
    if(N==0){
      putchar_unlocked('\n');
    }
    else{
      for(KL2GvlyY=0;KL2GvlyY<N-1;KL2GvlyY++){
        wt_L(2*res[KL2GvlyY]);
        wt_L(' ');
      }
      wt_L(2*res[KL2GvlyY]);
      wt_L('\n');
    }
  }
  return 0;
}
// cLay varsion 20190708-1

// --- original code ---
// int N, A[1d5];
// int res[1d5];
// {
//   int i, x;
//
//   rd(N,A(N));
//   rep(i,1,N) res[i] = A[i-1] - res[i-1];
//
//   x = (A[N-1] - res[N-1]) / 2;
//   rep(i,N) res[i] if[i%2==0, +=, -=] x;
//
//   wt(2res(N));
// }


#pragma GCC optimize ("O3")
#include "bits/stdc++.h"

using namespace std;
using ll = long long int;

#define debugos cout
#define debug(v) {printf("L%d %s > ",__LINE__,#v);debugos<<(v)<<endl;}
#define debugv(v) {printf("L%d %s > ",__LINE__,#v);for(auto e:(v)){debugos<<e<<" ";}debugos<<endl;}
#define debuga(m,w) {printf("L%d %s > ",__LINE__,#m);for(int x=0;x<(w);x++){debugos<<(m)[x]<<" ";}debugos<<endl;}
#define debugaa(m,h,w) {printf("L%d %s >\n",__LINE__,#m);for(int y=0;y<(h);y++){for(int x=0;x<(w);x++){debugos<<(m)[y][x]<<" ";}debugos<<endl;}}
#define all(v) (v).begin(),(v).end()
#define repeat(cnt,l) for(auto cnt=decltype(l)();(cnt)<(l);++(cnt))
#define rrepeat(cnt,l) for(auto cnt=(l)-1;0<=(cnt);--(cnt))
#define iterate(cnt,b,e) for(auto cnt=(b);(cnt)!=(e);++(cnt))
#define diterate(cnt,b,e) for(auto cnt=(b);(cnt)!=(e);--(cnt))
const ll MD = 1000000007ll; const long double PI = 3.1415926535897932384626433832795L;
inline void assert_call(bool assertion, function<void()> f) { if (!assertion) { cerr << "assertion fault:" << endl; f(); abort(); } }
template<typename T1, typename T2> inline ostream& operator <<(ostream &o, const pair<T1, T2> p) { o << '(' << p.first << ':' << p.second << ')'; return o; }
template<typename Vec> inline ostream& _ostream_vecprint(ostream& os, const Vec& a) {
    os << '['; for (const auto& e : a) os << ' ' << e << ' '; os << ']'; return os; }
template<typename T> inline ostream& operator<<(ostream& o, const vector<T>& v) { return _ostream_vecprint(o, v); }
template<typename T, size_t S> inline ostream& operator<<(ostream& o, const array<T, S>& v) { return _ostream_vecprint(o, v); }
template<typename T> inline T& chmax(T& to, const T& val) { return to = max(to, val); }
template<typename T> inline T& chmin(T& to, const T& val) { return to = min(to, val); }
void bye(string s, int code = 0) { cout << s << endl; exit(code); }
mt19937_64 randdev(8901016);
template<typename T, typename Random = decltype(randdev), typename enable_if<is_integral<T>::value>::type* = nullptr>
inline T rand(T l, T h, Random& rand = randdev) { return uniform_int_distribution<T>(l, h)(rand); }
template<typename T, typename Random = decltype(randdev), typename enable_if<is_floating_point<T>::value>::type* = nullptr>
inline T rand(T l, T h, Random& rand = randdev) { return uniform_real_distribution<T>(l, h)(rand); }

#if defined(_WIN32) || defined(_WIN64)
#define getc_x _getc_nolock
#define putc_x _putc_nolock
#elif defined(__GNUC__)
#define getc_x getc_unlocked
#define putc_x putc_unlocked
#else
#define getc_x getc
#define putc_x putc
#endif
#define isvisiblechar(c) (0x21<=(c)&&(c)<=0x7E)
class MaiScanner {
    FILE* fp_;
public:
    inline MaiScanner(FILE* fp):fp_(fp){}
    template<typename T> void input_integer(T& var) noexcept {
        var = 0; T sign = 1;
        int cc = getc_x(fp_);
        for (; cc < '0' || '9' < cc; cc = getc_x(fp_))
            if (cc == '-') sign = -1;
        for (; '0' <= cc && cc <= '9'; cc = getc_x(fp_))
            var = (var << 3) + (var << 1) + cc - '0';
        var = var * sign;
    }
    inline int c() noexcept { return getc_x(fp_); }
    inline MaiScanner& operator>>(int& var) noexcept { input_integer<int>(var); return *this; }
    inline MaiScanner& operator>>(long long& var) noexcept { input_integer<long long>(var); return *this; }
    inline MaiScanner& operator>>(string& var) {
        int cc = getc_x(fp_);
        for (; !isvisiblechar(cc); cc = getc_x(fp_));
        for (; isvisiblechar(cc); cc = getc_x(fp_))
            var.push_back(cc);
        return *this;
    }
    template<typename IT> inline void in(IT begin, IT end) { for (auto it = begin; it != end; ++it) *this >> *it; }
};
class MaiPrinter {
    FILE* fp_;
public:
    inline MaiPrinter(FILE* fp):fp_(fp){}
    template<typename T>
    void output_integer(T var) noexcept {
        if (var == 0) { putc_x('0', fp_); return; }
        if (var < 0)
            putc_x('-', fp_),
            var = -var;
        char stack[32]; int stack_p = 0;
        while (var)
            stack[stack_p++] = '0' + (var % 10),
            var /= 10;
        while (stack_p)
            putc_x(stack[--stack_p], fp_);
    }
    inline MaiPrinter& operator<<(char c) noexcept { putc_x(c, fp_); return *this; }
    inline MaiPrinter& operator<<(int var) noexcept { output_integer<int>(var); return *this; }
    inline MaiPrinter& operator<<(long long var) noexcept { output_integer<long long>(var); return *this; }
    inline MaiPrinter& operator<<(char* str_p) noexcept { while (*str_p) putc_x(*(str_p++), fp_); return *this; }
    inline MaiPrinter& operator<<(const string& str) {
        const char* p = str.c_str();
        const char* l = p + str.size();
        while (p < l) putc_x(*p++, fp_);
        return *this;
    }
    template<typename IT> void join(IT begin, IT end, char sep = ' ') { for (bool b = 0; begin != end; ++begin, b = 1) b ? *this << sep << *begin : *this << *begin; }
};
MaiScanner scanner(stdin);
MaiPrinter printer(stdout);

//

int N;
ll A[100010];

//

int main() {
    scanner >> N;
    scanner.in(A, A+N);

    ll l = A[0];
    repeat(i, N - 1){
        l = A[i+1] - l;
    }

    printer << l << ' ';
    repeat(i, N - 1) {
        l = 2*A[i] - l;
        printer << l << ' ';
    }

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i,n) for(int i=0; i<(int)n; i++)
#define rep1(i,n) for(int i=1; i<(int)n; i++)
#define repa(i,a,n) for(int i=(a); i<(int)(n); i++)
#define all(vec) vec.begin(),vec.end()
#define COUT(x) cout<<(x)<<endl
#define YES(x) cout<<(x?"YES":"NO")<<endl
#define Yes(x) cout<<(x?"Yes":"No")<<endl
using vi = vector<int>;
using vs = vector<string>;
using vvi = vector<vi>;
using pii = pair<int, int>;
using psi = pair<string, int>;
const int dx[4] = {1, 0,-1, 0};
const int dy[4] = {0, 1, 0,-1};
const int mod = 1e9+7;
int gcd(int a, int b){if(a%b == 0){return(b);}else{return(gcd(b, a%b));}}
int lcm(int a, int b){return a / gcd(a, b)*b;}
//cout << fixed << setprecision(15);
int N, M, K, H, W, L, R, X, Y;
string S, T;

signed main(){
  cin >> N;
  vi D(N);
  rep(i,N) cin >> D[i];
  vi Y(N);
  for(int i = 2*min(D[0],D[N-1]); i>=0; i -= 2){
    Y[0] = i;
    bool chk = true;
    rep1(j,N){
      Y[j] = (D[j-1]-Y[j-1]/2)*2;
      if(Y[j]<0){i += (Y[j]+1)*2 ; chk = false; break;}
    }
    if(!chk) continue;
    if((Y[N-1]+Y[0])/2 == D[N-1]) break;
  }

  rep(i,N) {
    cout << Y[i];
    if(i!=N-1) cout << " ";
  }
  cout << endl;
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i,n) for(int i=0; i<(int)n; i++)
#define rep1(i,n) for(int i=1; i<(int)n; i++)
#define repa(i,a,n) for(int i=(a); i<(int)(n); i++)
#define all(vec) vec.begin(),vec.end()
#define COUT(x) cout<<(x)<<endl
#define YES(x) cout<<(x?"YES":"NO")<<endl
#define Yes(x) cout<<(x?"Yes":"No")<<endl
using vi = vector<int>;
using vs = vector<string>;
using vvi = vector<vi>;
using pii = pair<int, int>;
using psi = pair<string, int>;
const int dx[4] = {1, 0,-1, 0};
const int dy[4] = {0, 1, 0,-1};
const int mod = 1e9+7;
int gcd(int a, int b){if(a%b == 0){return(b);}else{return(gcd(b, a%b));}}
int lcm(int a, int b){return a / gcd(a, b)*b;}
//cout << fixed << setprecision(15);
int N, M, K, H, W, L, R, X, Y;
string S, T;

signed main(){
  cin >> N;
  vi D(N);
  rep(i,N) cin >> D[i];
  vi Y(N);
  for(int i = 2*min(D[0],D[N-1]); i>=0; i -= 2){
    Y[0] = i;
    bool chk = true;
    rep1(j,N){
      Y[j] = (D[j-1]-Y[j-1]/2)*2;
      if(Y[j]<0){i += Y[j]*2 ; chk = false; break;}
    }
    if(!chk) continue;
    if((Y[N-1]+Y[0])/2 == D[N-1]) break;
  }

  rep(i,N) {
    cout << Y[i];
    if(i!=N-1) cout << " ";
  }
  cout << endl;
  return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i,n) for(int i=0; i<(int)n; i++)
#define rep1(i,n) for(int i=1; i<(int)n; i++)
#define repa(i,a,n) for(int i=(a); i<(int)(n); i++)
#define all(vec) vec.begin(),vec.end()
#define COUT(x) cout<<(x)<<endl
#define YES(x) cout<<(x?"YES":"NO")<<endl
#define Yes(x) cout<<(x?"Yes":"No")<<endl
using vi = vector<int>;
using vs = vector<string>;
using vvi = vector<vi>;
using pii = pair<int, int>;
using psi = pair<string, int>;
const int dx[4] = {1, 0,-1, 0};
const int dy[4] = {0, 1, 0,-1};
const int mod = 1e9+7;
int gcd(int a, int b){if(a%b == 0){return(b);}else{return(gcd(b, a%b));}}
int lcm(int a, int b){return a / gcd(a, b)*b;}
//cout << fixed << setprecision(15);
int N, M, K, H, W, L, R, X, Y;
string S, T;

signed main(){
  cin >> N;
  vi D(N);
  rep(i,N) cin >> D[i];
  vi Y(N);
  for(int i = 2*min(D[0],D[N-1]); i>=0; i -= 2){
    Y[0] = i;
    bool chk = true;
    rep1(j,N){
      Y[j] = (D[j-1]-Y[j-1]/2)*2;
      if(Y[j]<0){chk = false; break;}
    }
    if(!chk) continue;
    if((Y[N-1]+Y[0])/2 == D[N-1]) break;
  }

  rep(i,N) {
    cout << Y[i];
    if(i!=N-1) cout << " ";
  }
  cout << endl;
  return 0;
}


// AtCoder ABC133: D - Rain Flows into Dams
// 2019.9.3 bal4u

#include <stdio.h>

typedef long long ll;

//// 高速入力
#if 1
#define gc() getchar_unlocked()
#define pc(c) putchar_unlocked(c)
#else
#define gc() getchar()
#define pc(c) putchar(c)
#endif

int in() {   // 非負整数の入力
	int n = 0, c = gc();
	do n = 10 * n + (c & 0xf); while ((c = gc()) >= '0');
	return n;
}

void out(ll n) { // 非負整数の表示（出力）
	int i; char b[30];

	if (!n) pc('0');
	else {
		i = 0; while (n) b[i++] = n % 10 + '0', n /= 10;
		while (i--) pc(b[i]);
	}
}

ll  b[100005];

int main()
{
	int i, N; ll a, x;

	N = in();
	for (i = 1; i <= N; i++) {
		a = in();
		b[i] = (a << 1) - b[i-1];
	}
	x = b[N] >> 1, out(x);
	for (i = 1; i < N; i++) {
		pc(' ');
		if (i & 1) out(b[i]-x);
		else       out(b[i]+x);
	}
	pc('\n');
	return 0;
}


#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <ctype.h>
#define MOD 2019
#define MAX(a,b) (a>b?a:b)
#define MAX3(a,b,c) MAX(a,MAX(b,c))
#define MIN(a,b) (a<b?a:b)
#define MIN3(a,b,c) MIN(a, MIN(b,c))
typedef long long lli;
int cmp(const void *a, const void *b) {
    return *(int*)a - *(int*)b;
}

int main()
{
    lli i, j, n, a[100000],sum=0,a0,a1;
    scanf("%lld",&n);
    for(i=0; i<n; i++) {
        scanf("%lld",a+i);
        a[i] *= 2;
        sum += a[i];
    }
    sum /= 2;
    a0 = a1 = sum;
    for(i=1; i<n; i+=2) {
        a0 -= a[i];
        a1 -= a[i+1];
    }
    for(i=0; i<n-1; i+=2) {
        printf("%lld %lld ",a0,a1);
        a0 = a0 + a[i+1] - a[i];
        a1 = a1 + a[i+2] - a[i+1];
    }
    printf("%lld",a0);
    return 0;
}


#include <stdio.h>

int main()
{   int n;
    scanf("%d",&n);
    long a[n],sum=0;
    for(int i=0;i<n;i++){
        scanf("%ld",&a[i]);
        sum+=a[i];
    }
    int x[100000]={0};
    x[0]=sum;
    for(int i=1;i<n;i+=2){
        x[0]-=2*a[i];
    }
    printf("%d ",x[0]);
    for(int i=1;i<n;i++){
        x[i]=2*a[i-1]-x[i-1];
        printf("%d ",x[i]);
    }

    return 0;
}


#include <stdio.h>

int main()
{
	int i, N;
	long long A[100000];
	scanf("%d", &N);
	for (i = 1; i <= N; i++) scanf("%d", &(A[i]));

	long long sum = 0, tmp;
	for (i = 1; i <= N; i++) sum += A[i];
	for (i = 1, tmp = sum; i <= N / 2; i++) tmp -= A[i*2] * 2;
	printf("%lld ", tmp);
	for (i = 2; i <= N; i++) {
		tmp = A[i-1] * 2 - tmp;
		printf("%lld ", tmp);
	}
	fflush(stdout);
	return 0;
}


N = int(input())
A = list(map(int, input().split(' ')))
a = 0
for i in range(N):
  a += (-1) ** i * A[i]
res = [0 for _ in range(N)]
res[0] = a
print('{} '.format(res[0]), end='')
for i in range(1, N - 1):
  res[i] = 2 * A[i-1] - res[i-1]
  print('{} '.format(res[i]), end='')
res[N-1] = 2 * A[N-2] - res[N-2]
print(res[N-1])


#include<stdio.h>
int main(){
  int n,i,j;
  scanf("%d",&n);
  long long mount[n+1],dam[n+1];
  for(i=0;i<n;i++){
    scanf("%lld",&dam[i]);
    mount[i]=dam[i];
  }
  for(i=0;i<n;i++)
    for(j=0;j<n/2;j++)
      mount[i]+=dam[(i+j*2+2)%n]-dam[(i+j*2+1)%n];
  for(i=0;i<n;i++)
    printf("%lld ",mount[i]);
  return 0;
}


//↓見なくていいよ！ここから--------------------------------------------------
var read = require('readline').createInterface({
  input: process.stdin,
  output: process.stdout
});
var obj;
var inLine = [];
read.on('line', function(input){inLine.push(input);});
read.on('close', function(){
  obj = init(inLine);
  console.error("\n");
  var start = new Date();
  Main();
  var end = new Date() - start;

  myerr("time : " + (end) + "ms");
  myerr("memory : " + Math.round(process.memoryUsage().heapTotal / 1024) + "KB");
});
function makeClone(obj){return JSON.parse(JSON.stringify(obj));}
function nextInt(){return myconv(next(),1);} function nextStrArray(){return myconv(next(),2);}
function nextIntArray(){return myconv(next(),4);} function nextCharArray(){return myconv(next(),6);}
function next(){return obj.next();} function hasNext(){return obj.hasNext();}
function init(input){
  var returnObj = {
    list : input, index : 0, max : input.length,
    hasNext : function(){return (this.index < this.max);},
    next : function(){if(!this.hasNext()){throw "ArrayIndexOutOfBoundsException これ以上ないよ";}else{var returnInput = this.list[this.index];this.index++;return returnInput;}}
  };
  return returnObj;
}
function myout(s){console.log(s);}
function myerr(s){console.error("debug:" + require("util").inspect(s,false,null));}
//[no]要素の扱い。数値型
//不明値、異常時:引数そのまま返す 1:数値へ変換
//2:半角SPで分割 4:半角SPで分割し、数値配列へ
//6:1文字で分割  7:1文字で分割し、数値配列へ
//8:半角SPで結合 9:改行で結合 0:文字なしで結合
function myconv(i,no){try{switch(no){case 1:return parseInt(i);case 2:return i.split(" ");case 4:return i.split(" ").map(Number);case 6:return i.split("");case 7:return i.split("").map(Number);case 8:return i.join(" ");case 9:return i.join("\n");case 0:return i.join("");default:return i;}}catch(e){return i;}}

//↑見なくていいよ！ここまで--------------------------------------------------
function Main(){
	var N = nextInt();
	var list = nextIntArray();
	var sum = 0;
	for(var i = 0; i < N; i++){
		if(i % 2 == 0){
			sum += list[i] * 2;
		}else{
			sum -= list[i] * 2;
		}
	}
	var output = new Array(N);
	output[0] = sum / 2;
	for(var i = 1; i < N; i++){
		output[i] = list[i - 1] * 2 - output[i - 1];
	}
	myout(myconv(output,8));
}


// inputに入力データ全体が入る
function Main(input) {
	// 1行目がinput[0], 2行目がinput[1], …に入る
	input = input.split("\n");
	tmp = input[1].split(" ");
	//文字列から10進数に変換するときはparseIntを使います
	var N = parseInt(input[0], 10);

	var valley = toIntAll(tmp);
	var sumValley=0;
	for(var i=0; i<valley.length; i++){
		sumValley += valley[i];
	}

	var tmpSum = 0;
	for(var i=1; i<valley.length; i+=2){
		tmpSum += valley[i];
	}
	tmpMountainZero = sumValley - (2*tmpSum);

	var tmpMountain = [];
	tmpMountain[0] = tmpMountainZero;
	for(var i=1; i<valley.length; i++){
		tmpMountain[i] = (valley[i-1] - (tmpMountain[i-1]/2)) * 2;
	}
	//出力
	console.log('%s', outputDelimiterSpace(tmpMountain));
}
function toIntAll(input){
  var out = []
  for(var i=0; i<input.length; i++){
    out[i] = parseInt(input[i]);
  }
  return out;
}
function outputDelimiterSpace(words){
  var out = words.join(' ');
  out += '\n';
  return out;
}

//*この行以降は編集しないでください（標準入出力から一度に読み込み、Mainを呼び出します）
Main(require("fs").readFileSync("/dev/stdin", "utf8"));


function myout(text){console.log(text);}//standard output
function Main(input) {
	//input = parseInt(input);
	//input = input.split(" ");
	input = input.split("\n");
	//input = input.split(" ").map((a)=>Number(a));
	//input = input.split("\n").map((a)=>Number(a));
  var N = parseInt(input[0]);
  var list = input[1].split(" ").map((a)=>Number(a));
  var ruiseki = 0;
  for(var i = 0; i < list.length; i++){
    ruiseki += list[i];
  }
  var result = [];
  var tmp = 0;//x1を求めるとき用に偶数要素の累積を持たせる
  for(var i = 1; i < list.length; i = i + 2){
    tmp += list[i];
  }
  result[0] = ruiseki - 2 * tmp;
  for(var i = 1; i < list.length; i++){
    result.push(2 * list[i - 1] - result[i - 1]);
  }
  myout(result.join(" "));
}

Main(require("fs").readFileSync("/dev/stdin", "utf8").trim());


function main(input){
  const args=input.split("\n");
  const N=parseInt(args[0],10);

  //A1,A2,…という配列
  const arr=input.split('\n')[1].split(' ').map((n) => parseInt(n, 10));

  for(var i=0; i<N; i++){
    var k=0;
    for(var j=0; j<N; j++){
      k+=arr[(i+j)%N]*Math.pow(-1,j);
    }
    console.log(k+" ");
  }
}

main(require('fs').readFileSync('/dev/stdin', 'utf8'))


'use strict'
function main(input) {
    const tmp = Array.from(input.split('\n'));
    const N = parseInt(tmp[0], 10);
    const A = tmp[1].split(' ').map((elem) => parseInt(elem, 10));

    let X = [];
    const S = A.reduce((sum, elem) => sum + elem);
    const A2 = A.filter((elem, i) => i % 2 !== 0).reduce((sum, elem) => sum + elem);
    X[0] = S - 2 * A2;

    for (let i = 1; i < N; i++) {
        X[i] = 2 * A[i - 1] - X[i - 1];
    }

    console.log(X);
}

main(require('fs').readFileSync('/dev/stdin', 'utf8'));


function Main(input){
  input = input.split("\n");
  //山の数Ｎを格納する
  inputStr = input[0].split(" ");
  const N = Number.parseInt(inputStr[0]);
  //数値変換しつつ配列D_arrとしてダムに溜まった水を格納する
  var D_arr = input[1].split(" ");
  //山に降った雨の量を計算。配列A_arrに溜め込む
  var A_arr = [];
  for( i1=0; i1 < N ;i1++){
    A_arr.push(0);
  }
  //計算する
  for( var i2 = 0; i2 < N ; i2++){
　　//自分の山に半分
    A_arr[i2] += D_arr[i2]/2;
    if(i2===N-1){
      A_arr[0] += D_arr[i2]/2;
    } else {
      A_arr[i2+1] += D_arr[i2]/2;
    }
  }
  //ここまでだと降水量に奇数と成り得る為ダムの水量を見ながら補正計算

  //結果を出力
  console.log(A_arr.join(" "));
}
Main(require("fs").readFileSync("/dev/stdin", "utf8"));


package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	sc := NewScanner()
	N := sc.NextInt()
	A := sc.NextIntArray()

	S := 0
	P := 0
	for i := 0; i < N; i++ {
		S += A[i]
		if i%2 == 1 {
			P += A[i]
		}
	}

	X := make([]int, N)

	X[0] = S - 2*P
	for i := 1; i < N; i++ {
		X[i] = 2*A[i-1] - X[i-1]
	}
	PrintI(X...)
}

func mapToString(arr []int) []string {
	ret := make([]string, len(arr))
	for i := 0; i < len(arr); i++ {
		ret[i] = strconv.Itoa(arr[i])
	}
	return ret
}

func PrintI(args ...int) {
	fmt.Println(strings.Join(mapToString(args), " "))
}

type Scanner struct {
	r   *bufio.Reader
	buf []byte
	p   int
}

func NewScanner() *Scanner {
	rdr := bufio.NewReaderSize(os.Stdin, 1000)
	return &Scanner{r: rdr}
}
func (s *Scanner) Next() string {
	s.pre()
	start := s.p
	for ; s.p < len(s.buf); s.p++ {
		if s.buf[s.p] == ' ' {
			break
		}
	}
	result := string(s.buf[start:s.p])
	s.p++
	return result
}
func (s *Scanner) NextLine() string {
	s.pre()
	start := s.p
	s.p = len(s.buf)
	return string(s.buf[start:])
}
func (s *Scanner) NextInt() int {
	v, _ := strconv.Atoi(s.Next())
	return v
}
func (s *Scanner) NextInt64() int64 {
	v, _ := strconv.ParseInt(s.Next(), 10, 64)
	return v
}

func (s *Scanner) NextFloat() float64 {
	v, _ := strconv.ParseFloat(s.Next(), 64)
	return v
}

func (s *Scanner) NextIntArray() []int {
	s.pre()
	start := s.p
	result := []int{}
	for ; s.p < len(s.buf)+1; s.p++ {
		if s.p == len(s.buf) || s.buf[s.p] == ' ' {
			v, _ := strconv.ParseInt(string(s.buf[start:s.p]), 10, 0)
			result = append(result, int(v))
			start = s.p + 1
		}
	}

	return result
}
func (s *Scanner) NextInt64Array() []int64 {
	s.pre()
	start := s.p
	result := []int64{}
	for ; s.p < len(s.buf)+1; s.p++ {
		if s.p == len(s.buf) || s.buf[s.p] == ' ' {
			v, _ := strconv.ParseInt(string(s.buf[start:s.p]), 10, 64)
			result = append(result, v)
			start = s.p + 1
		}
	}
	return result
}

func (s *Scanner) NextMap() map[int]bool {
	s.pre()
	start := s.p
	mp := map[int]bool{}
	for ; s.p < len(s.buf); s.p++ {
		if s.buf[s.p] == ' ' {
			v, _ := strconv.Atoi(string(s.buf[start:s.p]))
			mp[v] = true
			start = s.p + 1
		}
	}
	v, _ := strconv.Atoi(string(s.buf[start:s.p]))
	mp[v] = true

	return mp
}

func (s *Scanner) pre() {
	if s.p >= len(s.buf) {
		s.readLine()
		s.p = 0
	}
}
func (s *Scanner) readLine() {
	s.buf = make([]byte, 0)
	for {
		l, p, e := s.r.ReadLine()
		if e != nil {
			panic(e)
		}
		s.buf = append(s.buf, l...)
		if !p {
			break
		}
	}
}


package main

import (
	"bufio"
	// "fmt"
	"os"
	"strconv"
)

var sc = bufio.NewScanner(os.Stdin)
var wr = bufio.NewWriter(os.Stdout)

func nextInt() int {
	i, e := strconv.Atoi(nextString())
	if e != nil {
		panic(e)
	}
	return i
}

func nextInt64() int64 {
	i, e := strconv.ParseInt(nextString(), 10, 64)
	if e != nil {
		panic(e)
	}
	return i
}

func nextString() string {
	sc.Scan()
	return sc.Text()
}

func putInt64(i int64) {
	wr.WriteString(strconv.FormatInt(i, 10))
	// wr.Flush()
}
func putString(s string) {
	wr.WriteString(s)
	// wr.Flush()
}

func main() {
	sc.Buffer(make([]byte, 0), 1000000009)
	sc.Split(bufio.ScanWords)

	var n int
	n = nextInt()

	a := make([]int, n)

	for i := 0; i < n; i++ {
		a[i] = nextInt()
	}

	var ans int64

	for i := 0; i < n; i++ {
		ans += int64(a[i])
		if i%2 == 1 {
			ans -= 2 * int64(a[i])
		}
	}

	for i := 0; i < n; i++ {
		putInt64(ans)
		ans = 2*int64(a[i]) - ans
		if i == n-1 {
			putString("\n")
		} else {
			putString(" ")
		}
	}
	wr.Flush()
}


package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

func main() {
	var n int
	fmt.Scan(&n)
	sc := bufio.NewScanner(os.Stdin)
	sc.Split(bufio.ScanWords)
	a := make([]int, n)
	x := 0
	for i := range a {
		sc.Scan()
		a[i], _ = strconv.Atoi(sc.Text())
		x += a[i]
	}

	for i := 2; i < n; i += 2 {
		x -= 2 * a[i-1]
	}
	fmt.Print(x)

	wr := bufio.NewWriter(os.Stdout)
	for i := 0; i < n-1; i++ {
		x = a[i]*2 - x
		wr.WriteString(" " + strconv.Itoa(x))
	}
	wr.WriteString("\n")
	wr.Flush()
}


package main

import (
	"bufio"
	"bytes"
	"fmt"
	"io"
	"os"
	"strconv"
)

var DEBUG = false

// -----------------------------------------------------------------------------

// IO helper functions

// Returns next token from input.  It must be initialized by SetInput()
// before the first call.
var nextToken func() ([]byte, error)
var nextLine func() ([]byte, error)

// Holds a buffer for output.  It must be initialized by SetOutput().
// All IO functions (read*() and [e]print*()) should write to OutputWriter
// instead of this.
var OutputBuffer *bufio.Writer

// Holds an io.Writer.  It must be initialized by SetOutput()
var OutputWriter io.Writer

// Set IO functions for interactive input/output.
func SetInteractive(w io.Writer, r io.Reader) {
	SetUnbufferedInput(r)
	OutputBuffer = nil
	OutputWriter = w
}

// Setup OutputBuffer and OutputWriter.
func SetOutput(w io.Writer) {
	OutputBuffer = bufio.NewWriter(w)
	OutputWriter = OutputBuffer
}

// Flushes OutputBuffer
func Flush() {
	if OutputBuffer != nil {
		OutputBuffer.Flush()
	}
}

// Returns true if c is a white space
func IsSpace(c byte) bool {
	switch c {
	case '\t', '\n', '\v', '\f', '\r', ' ':
		return true
	}
	return false
}

func IsNewLine(c byte) bool {
	switch c {
	case '\n', '\r':
		return true
	}
	return false
}

// Setup nextToken with input buffer.
func SetInput(r io.Reader) {
	buf := new(bytes.Buffer)
	var b []byte

	var i int
	rest := func() ([]byte, error) {
		for i < len(b) && IsSpace(b[i]) {
			i++
		}
		if i == len(b) {
			return nil, io.ErrUnexpectedEOF
		}
		j := i
		for i < len(b) && !IsSpace(b[i]) {
			i++
		}
		return b[j:i], nil
	}
	initial := func() ([]byte, error) {
		io.Copy(buf, r)
		b = buf.Bytes()
		nextToken = rest
		return rest()
	}
	nextToken = initial

	restLn := func() ([]byte, error) {
		for i < len(b) && IsNewLine(b[i]) {
			i++
		}
		if i == len(b) {
			return nil, io.ErrUnexpectedEOF
		}
		j := i
		for i < len(b) && !IsNewLine(b[i]) {
			i++
		}
		return b[j:i], nil
	}

	initialLn := func() ([]byte, error) {
		io.Copy(buf, r)
		b = buf.Bytes()
		nextLine = restLn
		return restLn()
	}
	nextLine = initialLn
}

// Setup nextToken without input buffer.
func SetUnbufferedInput(r io.Reader) {
	buf := bufio.NewReader(r)
	var b []byte

	var i int
	nextToken = func() ([]byte, error) {
		var err error
		if i == len(b) {
			b, err = buf.ReadBytes('\n')
			if err != nil {
				return nil, err
			}
			i = 0
			j := len(b) - 1
			for 0 <= j && IsSpace(b[j]) {
				j--
			}
			b = b[0 : j+1]
		}
		for i < len(b) && IsSpace(b[i]) {
			i++
		}
		j := i
		for i < len(b) && !IsSpace(b[i]) {
			i++
		}
		if i == j {
			return nil, io.ErrUnexpectedEOF
		}
		return b[j:i], nil
	}
}

// -----------------------------------------------------------------------------

// IO functions

// Reads next token and return it as []byte
func readb() []byte {
	b, err := nextToken()
	if err != nil {
		panic(err)
	}
	return b[:len(b):len(b)]
}

// Reads next token and return it as string
func reads() string {
	return string(readb())
}

// Read next line as []byte.  Trailing '\n' will not be included.
// See also comments on readb()
func readbln() []byte {
	b, err := nextLine()
	if err != nil {
		panic(err)
	}
	return b[:len(b):len(b)]
}

// Read next line as string
func readsln() string {
	return string(readbln())
}

// Reads next token and return it as int64
func readll() int64 {
	i, err := strconv.ParseInt(reads(), 10, 64)
	if err != nil {
		panic(err.Error())
	}
	return i
}

// Reads next token and return it as int
func readi() int {
	return int(readll())
}

// Reads next token and return it as float64
func readf() float64 {
	f, err := strconv.ParseFloat(reads(), 64)
	if err != nil {
		panic(err.Error())
	}
	return f
}

// Write args to OutputWriter with the format f
func printf(f string, args ...interface{}) (int, error) {
	return fmt.Fprintf(OutputWriter, f, args...)
}

// Write args to OutputWriter without format
func println(args ...interface{}) (int, error) {
	return fmt.Fprintln(OutputWriter, args...)
}

// Write args to stderr with the format f
func eprintf(f string, args ...interface{}) (int, error) {
	return fmt.Fprintf(os.Stderr, f, args...)
}

// Write args to stderr without format
func eprintln(args ...interface{}) (int, error) {
	return fmt.Fprintln(os.Stderr, args...)
}

func debugf(f string, args ...interface{}) {
	if !DEBUG {
		return
	}
	fmt.Fprintf(os.Stderr, f, args...)
}

func debug(args ...interface{}) {
	if !DEBUG {
		return
	}
	fmt.Fprintln(os.Stderr, args...)
}

// -----------------------------------------------------------------------------

// Utilities

func sumSlice(a []int) int {
	var res int
	for _, v := range a {
		res += v
	}
	return res
}

func sumSlicell(a []int64) int64 {
	var res int64
	for _, v := range a {
		res += v
	}
	return res
}

func readInts(N int) (int, []int) {
	if N == 0 {
		N = readi()
	}
	a := make([]int, N)
	for i := range a {
		a[i] = readi()
	}
	return N, a
}

func readIntsll(N int) (int, []int64) {
	if N == 0 {
		N = readi()
	}
	a := make([]int64, N)
	for i := range a {
		a[i] = readll()
	}
	return N, a
}

// -----------------------------------------------------------------------------

// Simple math functions

const (
	// big prime
	INF  = 1000000007
	INF2 = 1000000009
	INF3 = 998244353
)

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func minll(a, b int64) int64 {
	if a < b {
		return a
	}
	return b
}

func minf(a, b float64) float64 {
	if a < b {
		return a
	}
	return b
}

func max(a, b int) int {
	if a < b {
		return b
	}
	return a
}

func maxll(a, b int64) int64 {
	if a < b {
		return b
	}
	return a
}

func maxf(a, b float64) float64 {
	if a < b {
		return b
	}
	return a
}

func abs(a int) int {
	if a < 0 {
		return -a
	}
	return a
}

func absll(a int64) int64 {
	if a < 0 {
		return -a
	}
	return a
}

func absf(a float64) float64 {
	if a < 0 {
		return -a
	}
	return a
}

// egcd(a, b) returns d, x, y:
//   d is gcd(a,b)
//   x, y are  integers that satisfy ax + by = d
func egcd(a, b int) (int, int, int) {
	if b == 0 {
		return a, 1, 0
	}
	d, x, y := egcd(b, a%b)
	return d, y, x - a/b*y
}

func egcdll(a, b int64) (int64, int64, int64) {
	if b == 0 {
		return a, 1, 0
	}
	d, x, y := egcdll(b, a%b)
	return d, y, x - a/b*y
}

func gcd(a, b int) int {
	d, _, _ := egcd(a, b)
	return d
}

func gcdll(a, b int64) int64 {
	d, _, _ := egcdll(a, b)
	return d
}

// set up IO functions
func init() {
	// for non-interactive
	SetInput(os.Stdin)
	SetOutput(os.Stdout)

	// Enable below when interactive.  Its ok to leave above intact.
	SetInteractive(os.Stdout, os.Stdin)
}

func main() {
	defer Flush()
	n := readi()
	_, a := readInts(n)
	answer := solve(n, a)
	for i, v := range answer {
		if i != n-1 {
			printf("%d ", v)
		}
	}
	println(answer[n-1])
}

func solve(n int, a []int) []int {
	// naive solution
	// assume mt i get water x litter
	//   dam i - 1 and dam i get 1/2 x liter
	// mt i: m[i]
	//   dam  a[i] = m[i] / 2 + m[i+1] / 2
	//             = m[i]
	// mt i+1:
	//   dam  a[i+1]
	// ...
	// mt[N-1]= (a[0] - r[0]) * 2 + r[N-1] * 2
	// mt[0]  = (a[1] - r[1]) * 2 + r[0] * 2
	// mt[1]  = (a[2] - r[2]) * 2 + r[1] * 2

	// 0 <= r[i] <= a[i]
	minI := 0
	minA := INF
	for i := 0; i < n; i++ {
		if a[i] < minA {
			minI = i
		}
	}

	ub := a[minI]
	lb := 0

	for ub-lb != 1 {
		mid := (ub + lb) / 2
		debug(ub, lb, mid)
		ans := make([]int, n)
		if res := condition(a, minI, mid, ans) - mid; res == 0 {
			return ans
		} else if res < 0 {
			debug("res < 0 ", res)
			ub = mid
		} else {
			debug("res > 0", res)
			lb = mid
		}
		debug(ans)
	}

	panic(fmt.Sprintf("could not solved %d %d", ub, lb))
}

func condition(a []int, l, r int, ans []int) int {
	nextR := r
	for i := 0; i < len(a); i++ {
		ai := l + i
		if ai >= len(a) {
			ai -= len(a)
		}
		ans[ai] = nextR * 2
		nextR = a[ai] - nextR
	}
	return nextR
}


package main

import (
	"bufio"
	"fmt"
	"math"
	"os"
	"strconv"
	"strings"
)

var sc = bufio.NewScanner(os.Stdin)
var out = bufio.NewWriter(os.Stdout)

func main() {
	/*/TODO:!!!!!!!テスト用!!!!!!!!!
	sc = bufio.NewScanner(strings.NewReader(`
									`))
	//TODO:!!!!!!!テスト用!!!!!!!!!*/

	buf := make([]byte, 1024*1024)
	sc.Buffer(buf, bufio.MaxScanTokenSize)
	sc.Split(bufio.ScanWords)
	defer out.Flush() // !!!!caution!!!! you must use Fprint(out, ) not Print()
	/* --- code --- */
	//fmt.Fprintln(out, "[DEBUG]", time.Now())

	n := nextInt()
	a := make([]int, n)
	all := 0

	for i := 0; i < n; i++ {
		a[i] = nextInt()
		all += a[i]
	}

	ans := make([]string, n)

	for i := 0; i < n; i++ {
		la := all
		for j := i % 2; j < i; j += 2 {
			la -= 2 * a[j]
		}
		for j := i + 1; j < n; j += 2 {
			la -= 2 * a[j]
		}
		ans[i] = strconv.Itoa(la)
	}

	//fmt.Fprintln(out, "[DEBUG]", a)
	fmt.Fprintln(out, strings.Join(ans, " "))
}

//------------------------------------------------------------------------------

// -*-*-*-*-*-*-*-*-
// * I/O utilities *
// -*-*-*-*-*-*-*-*-

func next() string {
	sc.Scan()
	return sc.Text()
}

func nextInt() int {
	a, _ := strconv.Atoi(next())
	return a
}

func nextFloat64() float64 {
	a, _ := strconv.ParseFloat(next(), 64)
	return a
}

func nextInts(n int) []int {
	ret := make([]int, n)
	for i := 0; i < n; i++ {
		ret[i] = nextInt()
	}
	return ret
}
func nextFloats(n int) []float64 {
	ret := make([]float64, n)
	for i := 0; i < n; i++ {
		ret[i] = nextFloat64()
	}
	return ret
}
func nextStrings(n int) []string {
	ret := make([]string, n)
	for i := 0; i < n; i++ {
		ret[i] = next()
	}
	return ret
}

func chars(s string) []string {
	ret := make([]string, len([]rune(s)))
	for i, v := range []rune(s) {
		ret[i] = string(v)
	}
	return ret
}

func absInt(x int) int {
	return int(math.Abs(float64(x)))
}
func minInt(x, y int) int {
	if x < y {
		return x
	}
	return y
}
func maxInt(x, y int) int {
	if x > y {
		return x
	}
	return y
}
func log10(x int) float64 {
	return math.Log10(float64(x))
}


package main

import (
	"bufio"
	"fmt"
	"math"
	"os"
	"strconv"
	"strings"
)

var sc = bufio.NewScanner(os.Stdin)
var out = bufio.NewWriter(os.Stdout)

func main() {
	/*/TODO:!!!!!!!テスト用!!!!!!!!!
	sc = bufio.NewScanner(strings.NewReader(`
									`))
	//TODO:!!!!!!!テスト用!!!!!!!!!*/

	buf := make([]byte, 1024*1024)
	sc.Buffer(buf, bufio.MaxScanTokenSize)
	sc.Split(bufio.ScanWords)
	defer out.Flush() // !!!!caution!!!! you must use Fprint(out, ) not Print()
	/* --- code --- */
	//fmt.Fprintln(out, "[DEBUG]", time.Now())

	n := nextInt()
	a := make([]int, n)
	all := 0

	for i := 0; i < n; i++ {
		a[i] = nextInt()
		all += a[i]
	}

	ans := make([]string, n)

	for i := 0; i < n; i++ {
		la := all
		for j := 0; j < n; j++ {
			if i < j && (j-i)%2 == 1 {
				la -= 2 * a[j]
			} else if i > j && (j-i)%2 == 0 {
				la -= 2 * a[j]
			}
		}
		ans[i] = strconv.Itoa(la)
	}

	//fmt.Fprintln(out, "[DEBUG]", a)
	fmt.Fprintln(out, strings.Join(ans, " "))
}

//------------------------------------------------------------------------------

// -*-*-*-*-*-*-*-*-
// * I/O utilities *
// -*-*-*-*-*-*-*-*-

func next() string {
	sc.Scan()
	return sc.Text()
}

func nextInt() int {
	a, _ := strconv.Atoi(next())
	return a
}

func nextFloat64() float64 {
	a, _ := strconv.ParseFloat(next(), 64)
	return a
}

func nextInts(n int) []int {
	ret := make([]int, n)
	for i := 0; i < n; i++ {
		ret[i] = nextInt()
	}
	return ret
}
func nextFloats(n int) []float64 {
	ret := make([]float64, n)
	for i := 0; i < n; i++ {
		ret[i] = nextFloat64()
	}
	return ret
}
func nextStrings(n int) []string {
	ret := make([]string, n)
	for i := 0; i < n; i++ {
		ret[i] = next()
	}
	return ret
}

func chars(s string) []string {
	ret := make([]string, len([]rune(s)))
	for i, v := range []rune(s) {
		ret[i] = string(v)
	}
	return ret
}

func absInt(x int) int {
	return int(math.Abs(float64(x)))
}
func minInt(x, y int) int {
	if x < y {
		return x
	}
	return y
}
func maxInt(x, y int) int {
	if x > y {
		return x
	}
	return y
}
func log10(x int) float64 {
	return math.Log10(float64(x))
}


N,*as=$<.read.split.map(&:to_i)

n = 0
as.each do |a|
    n = a - n
end

n = n / 2
ret = [n*2]
as[0..-2].each do |a|
    n = a - n
    ret << n*2
end

puts ret.join(' ')


n = gets.to_i
a = gets.split.map(&:to_i)

x = a.inject{|r, v| v - r} / 2
ans = []

n.times do |i|
    ans << 2 * x
    x = a[i] - x
end

puts ans.join(" ")


n = gets.to_i
as = gets.split.map(&:to_i)

sum = 0
s = 1
n.times do |i|
  sum += s * as[i]
  s *= -1
end

bs = []

0.upto(n-1) do |i|
  bs << sum
  sum = 2 * as[i] - sum
end

puts bs.join(' ')


n = gets.to_i
a = gets.chomp.split.map(&:to_i)
s = a.inject(:+) / 2
res = Array.new(n, 0)

n.times do |i|
  ((n + 1) / 2).times do |j|
    res[i] += a[(i + 2 * j) % n]
  end
end

puts res.map {|x| (x - s) * 2 }.join(" ")


require 'matrix'

n = gets.to_i
a = gets.split.map(&:to_i)
b = a * 2
ma = Matrix.rows([a])
mb = Matrix.rows([b])
1.upto(n - 1) do |i|
  if i.even?
    ma += mb.minor(0, 1, i, n)
  else
    ma -= mb.minor(0, 1, i, n)
  end
end
puts ma.to_a.flatten.join(' ')


def gauss_elim(a, b, n_a, n_b_col)
  (n_a - 1).times do |j|
    partial_pivoting(a, b, n_a, n_b_col, j)
    (j + 1).upto(n_a - 1) do |i|
      r = a[i][j].to_f / a[j][j].to_f
      j.upto(n_a - 1) do |k|
        a[i][k] = a[i][k].to_f - a[j][k].to_f * r
      end
      b[i] = b[i].to_f - b[j].to_f * r
    end
  end

  (n_a - 1).downto(0) do |i|
    r = b[i].to_f
    (i + 1).upto(n_a - 1) do |k|
      r = r - a[i][k].to_f * b[k].to_f
    end
    b[i] = r / a[i][i].to_f
  end
end

def partial_pivoting(a, b, n_a, n_b_col, j)
  amax = a[j][j].to_f.abs
  imax = j

  (j + 1).upto(n_a - 1) do |i|
    r = a[i][j].to_f.abs
    if r > amax
      amax = r
      imax = i
    end
  end

  return if j == imax
  n_a.times do |k|
    r = a[imax][k]
    a[imax][k] = a[j][k]
    a[j][k] = r
  end
end

n = gets.to_i
a = []
n.pred.times do |i|
  a[i] = [0] * i + [1] * 2 + [0] * (n - i - 2)
end
a << [1] + [0] * (n - 2) + [1]
b = gets.split.map(&:to_i)

n_a = n
n_b_col = 1

gauss_elim(a, b, n_a, n_b_col)

n.times do |i|
  printf("%d\s", b[i] * 2)
end


/*------------------------------------------------------------------*/
/*------------------------- begin template -------------------------*/
/*------------------------------------------------------------------*/

// ref: tanakh <https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8>
// diff: using Parser
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut parser = Parser::from_str($s);
        input_inner!{parser, $($r)*}
    };
    (parser = $parser:ident, $($r:tt)*) => {
        input_inner!{$parser, $($r)*}
    };
    (new_stdin_parser = $parser:ident, $($r:tt)*) => {
        let stdin = std::io::stdin();
        let reader = std::io::BufReader::new(stdin.lock());
        let mut $parser = Parser::new(reader);
        input_inner!{$parser, $($r)*}
    };
    ($($r:tt)*) => {
        input!{new_stdin_parser = parser, $($r)*}
    };
}

macro_rules! input_inner {
    ($parser:ident) => {};
    ($parser:ident, ) => {};
    ($parser:ident, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($parser, $t);
        input_inner!{$parser $($r)*}
    };
}

macro_rules! read_value {
    ($parser:ident, ( $($t:tt),* )) => {
        ( $(read_value!($parser, $t)),* )
    };
    ($parser:ident, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($parser, $t)).collect::<Vec<_>>()
    };
    ($parser:ident, chars) => {
        read_value!($parser, String).chars().collect::<Vec<char>>()
    };
    ($parser:ident, char_) => {
        read_value!($parser, String).chars().collect::<Vec<char>>()[0]
    };
    ($parser:ident, usize1) => {
        read_value!($parser, usize) - 1
    };
    ($parser:ident, i64_) => {
        $parser.fast_i64()
    };
    ($parser:ident, usize_) => {
        $parser.fast_i64() as usize
    };
    ($parser:ident, usize1_) => {
        ($parser.fast_i64() - 1) as usize
    };
    ($parser:ident, $t:ty) => {
        $parser.next::<$t>().expect("Parse error")
    };
}

use std::io;
use std::io::BufRead;
use std::str;

// ref: tatsuya6502 <https://qiita.com/tatsuya6502/items/cd448486f7ef7b5b8c7e>
// ref: wariuni <https://qiita.com/tatsuya6502/items/cd448486f7ef7b5b8c7e#comment-7040a5ae96305e884eb9>
// diff: using std::io::BufRead::fill_buf()
pub struct Parser<R> {
    pub reader: R,
    buf: Vec<u8>,
    pos: usize,
}

impl Parser<io::Empty> {
    pub fn from_str(s: &str) -> Parser<io::Empty> {
        Parser {
            reader: io::empty(),
            buf: s.as_bytes().to_vec(),
            pos: 0,
        }
    }
}

impl<R: BufRead> Parser<R> {
    pub fn new(reader: R) -> Parser<R> {
        Parser {
            reader: reader,
            buf: vec![],
            pos: 0,
        }
    }
    pub fn update_buf(&mut self) {
        self.buf.clear();
        self.pos = 0;
        loop {
            let (len, complete) = {
                let buf2 = self.reader.fill_buf().unwrap();
                self.buf.extend_from_slice(buf2);
                let len = buf2.len();
                (len, buf2[len - 1] <= 0x20)
            };
            self.reader.consume(len);
            if complete {
                break;
            }
        }
    }
    pub fn next<T: str::FromStr>(&mut self) -> Result<T, T::Err> {
        loop {
            let mut begin = self.pos;
            while begin < self.buf.len() && (self.buf[begin] <= 0x20) {
                begin += 1;
            }
            let mut end = begin;
            while end < self.buf.len() && (self.buf[end] > 0x20) {
                end += 1;
            }
            if begin != self.buf.len() {
                self.pos = end;
                return unsafe { str::from_utf8_unchecked(&self.buf[begin..end]) }.parse::<T>();
            } else {
                self.update_buf();
            }
        }
    }
    pub fn fast_i64(&mut self) -> i64 {
        loop {
            let mut begin = self.pos;
            while begin < self.buf.len() && (self.buf[begin] <= 0x20) {
                begin += 1;
            }
            if begin == self.buf.len() {
                self.update_buf();
                continue;
            }
            let mut res = 0;
            let (is_positive, mut end) = match self.buf[begin] {
                b'+' => (true, begin + 1),
                b'-' => (false, begin + 1),
                _ => (true, begin),
            };
            while end < self.buf.len() && (self.buf[end] > 0x20) {
                res = res * 10 + (self.buf[end] as i64 - '0' as i64);
                end += 1;
            }
            if begin != self.buf.len() {
                self.pos = end;
                return if is_positive { res } else { -res };
            } else {
                self.update_buf();
            }
        }
    }
}

#[allow(unused_imports)]
use std::cmp::*;
use std::fmt::Display;
use std::fmt::Write;

pub fn writeln_vec<T: Display>(s: &mut String, xs: &Vec<T>) {
    if xs.len() == 0 {
        writeln!(s, "");
    } else {
        write!(s, "{}", xs[0]);
        for x in xs.iter().skip(1) {
            write!(s, " {}", x);
        }
        writeln!(s, "");
    }
}

fn main() {
    input! {
        new_stdin_parser = parser,
    }
    let res = solve(&mut parser);
    print!("{}", res);
}

/*------------------------------------------------------------------*/
/*-------------------------- end template --------------------------*/
/*------------------------------------------------------------------*/

fn solve<R: BufRead>(parser: &mut Parser<R>) -> String {
    let mut buf = String::new();
    input! {
        parser = parser,
        n: usize,
        xs: [i64; n],
    }
    let mut t = 0;
    let mut ys = vec![0; n];
    for i in 0..n {
        if i % 2 == 0 {
            t += xs[i];
        } else {
            t -= xs[i];
        }
    }
    ys[0] = t;
    for i in 1..n {
        ys[i] = xs[i - 1] * 2 - ys[i - 1];
    }
    writeln_vec(&mut buf, &ys);
    buf
}


use std::io::*;
use utils::*;

pub fn main() {
    let i = stdin();
    let mut o = Vec::new();
    run(i.lock(), &mut o);
    stdout().write_all(&o).unwrap();
}

pub fn run<R: BufRead, W: Write>(i: R, o: &mut W) {
    let mut i = CpReader::new(i);
    let n = i.read::<usize>();
    let a = i.read_vec::<u32>(n);

    let mut r = a[0] as i64;
    for i in 1..a.len() {
        r = a[i] as i64 - r;
    }

    let mut r = (r / 2) as u32;
    for i in 0..a.len() {
        if i != 0 {
            write!(o, " ").unwrap();
        }
        write!(o, "{}", r * 2).unwrap();
        r = a[i] - r;
    }
    writeln!(o, "").unwrap();
}

pub mod utils {
    use super::*;

    pub struct CpReader<R: BufRead> {
        r: R,
        b: Vec<u8>,
    }
    impl<R: BufRead> CpReader<R> {
        pub fn new(r: R) -> Self {
            CpReader {
                r: r,
                b: Vec::new(),
            }
        }
        pub fn read_word(&mut self) -> &[u8] {
            self.b.clear();
            let mut consume = 0;
            loop {
                self.r.consume(consume);
                let b = self.r.fill_buf().unwrap();
                assert!(b.len() != 0);
                if let Some(p) = b.iter().position(|&x| x == b' ' || x == b'\n') {
                    self.b.extend_from_slice(&b[..p]);
                    consume = p + 1;
                    break;
                }
                self.b.extend_from_slice(b);
                consume = b.len();
            }
            self.r.consume(consume);
            &self.b
        }
        pub fn read_word_str(&mut self) -> &str {
            unsafe { std::str::from_utf8_unchecked(self.read_word()) }
        }

        pub fn read_line(&mut self) -> &[u8] {
            self.b.clear();
            self.r.read_until(b'\n', &mut self.b).unwrap();
            if self.b.last() == Some(&b'\n') {
                &self.b[..self.b.len() - 1]
            } else {
                &self.b
            }
        }
        pub fn read_line_str(&mut self) -> &str {
            unsafe { std::str::from_utf8_unchecked(self.read_line()) }
        }

        pub fn read<T: CpIn>(&mut self) -> T {
            T::read_from(self)
        }

        pub fn read_vec<T: CpIn>(&mut self, n: usize) -> Vec<T> {
            (0..n).map(|_| self.read()).collect()
        }
        pub fn read_iter<'a, T: CpIn>(&'a mut self, n: usize) -> CpIter<'a, R, T> {
            CpIter {
                r: self,
                n: n,
                _pd: Default::default(),
            }
        }
    }
    pub struct CpIter<'a, R: BufRead + 'a, T> {
        r: &'a mut CpReader<R>,
        n: usize,
        _pd: std::marker::PhantomData<fn() -> T>,
    }
    impl<'a, R: BufRead, T: CpIn> Iterator for CpIter<'a, R, T> {
        type Item = T;
        fn next(&mut self) -> Option<T> {
            if self.n == 0 {
                None
            } else {
                self.n -= 1;
                Some(self.r.read())
            }
        }
    }

    pub trait CpIn {
        fn read_from<R: BufRead>(r: &mut CpReader<R>) -> Self;
    }

    impl CpIn for u64 {
        fn read_from<R: BufRead>(r: &mut CpReader<R>) -> Self {
            read_u64_fast(&mut r.r)
        }
    }
    impl CpIn for i64 {
        fn read_from<R: BufRead>(r: &mut CpReader<R>) -> Self {
            read_i64_fast(&mut r.r)
        }
    }
    impl CpIn for char {
        fn read_from<R: BufRead>(r: &mut CpReader<R>) -> Self {
            let b = r.r.fill_buf().unwrap()[0] as char;
            r.r.consume(1);
            let s = r.r.fill_buf().unwrap()[0];
            assert!(s == b' ' || s == b'\n');
            r.r.consume(1);
            b
        }
    }

    macro_rules! cpin_tuple {
        ($($t:ident),*) => {
            impl<$($t: CpIn),*> CpIn for ($($t),*) {
                fn read_from<R: BufRead>(r: &mut CpReader<R>) -> Self {
                    ($($t::read_from(r)),*)
                }
            }
        };
    }

    macro_rules! cpin_cast {
        ($t_self:ty, $t_read:ty) => {
            impl CpIn for $t_self {
                fn read_from<R: BufRead>(r: &mut CpReader<R>) -> Self {
                    <$t_read>::read_from(r) as $t_self
                }
            }
        };
    }
    macro_rules! cpin_parse {
        ($t:ty) => {
            impl CpIn for $t {
                fn read_from<R: BufRead>(r: &mut CpReader<R>) -> Self {
                    r.read_word_str().parse().unwrap()
                }
            }
        };
    }
    cpin_cast!(usize, u64);
    cpin_cast!(u32, u64);
    cpin_cast!(u16, u64);
    cpin_cast!(i32, i64);
    cpin_cast!(i16, i64);
    cpin_cast!(i8, i64);

    cpin_parse!(f64);

    cpin_tuple!(T1, T2);
    cpin_tuple!(T1, T2, T3);
    cpin_tuple!(T1, T2, T3, T4);
    cpin_tuple!(T1, T2, T3, T4, T5);

    fn read_u64_fast<R: BufRead>(r: &mut R) -> u64 {
        let mut value = 0;
        loop {
            let mut idx = 0;
            let buf_len;
            {
                let buf = r.fill_buf().unwrap();
                buf_len = buf.len();
                assert!(buf_len != 0);
                while idx < buf_len && b'0' <= buf[idx] && buf[idx] <= b'9' {
                    value = value * 10 + (buf[idx] - b'0') as u64;
                    idx += 1;
                }
            }
            if idx < buf_len {
                r.consume(idx + 1);
                return value;
            }
            r.consume(idx);
        }
    }
    fn read_i64_fast<R: BufRead>(r: &mut R) -> i64 {
        let (consume, sign) = match r.fill_buf().unwrap()[0] {
            b'+' => (true, 1),
            b'-' => (true, -1),
            _ => (false, 1),
        };
        if consume {
            r.consume(1);
        }
        read_u64_fast(r) as i64 * sign
    }

}


use std::io::*;

const SP: u8 = b' ';
const LF: u8 = b'\n';

struct CharacterInput<'a> {
    locked_stdin: StdinLock<'a>,
    bytes_buffer: Vec<u8>,
}

impl<'a> CharacterInput<'a> {
    fn read(&mut self, delimiter: u8) -> &[u8] {
        self.bytes_buffer.clear();

        let mut len = self
            .locked_stdin
            .read_until(delimiter, &mut self.bytes_buffer)
            .unwrap();

        if len > 0 {
            len -= 1;
        }

        &self.bytes_buffer[0..len]
    }

    fn scan_u(&mut self, delimiter: u8) -> u32 {
        self.read(delimiter)
            .into_iter()
            .fold(0, |accumulator, byte| {
                (byte - b'0') as u32 + accumulator * 10
            })
    }

    fn scan_u_vec(&mut self, n: usize, separator: u8, delimiter: u8) -> Vec<u32> {
        let mut vector = Vec::with_capacity(n as usize);
        for _i in 0..n - 1 {
            vector.push(self.scan_u(separator));
        }
        vector.push(self.scan_u(delimiter));
        vector
    }
}

fn create_cin<'a>(input: StdinLock<'a>, buffer_capacity: usize) -> CharacterInput {
    CharacterInput {
        locked_stdin: input,
        bytes_buffer: Vec::with_capacity(buffer_capacity),
    }
}

struct CharacterOutput {
    string_buffer: String,
}

impl CharacterOutput {
    fn push_s(&mut self, s: &str) {
        self.string_buffer += s;
    }

    fn push<T: ToString>(&mut self, n: T) {
        self.push_s(&n.to_string());
    }

    fn add<T: ToString>(&mut self, n: T, separator: char) {
        self.push(n);
        self.string_buffer.push(separator);
    }

    fn add_from_iterator<T: ToString, I>(
        &mut self,
        iterator: &mut I,
        length: usize,
        separator: char,
        delimiter: char,
    ) where
        I: Iterator<Item = T>,
    {
        for element in iterator.by_ref().take(length - 1) {
            self.add(element, separator);
        }
        self.add(iterator.next().unwrap(), delimiter);
    }

    fn flush(&mut self) {
        let out = stdout();
        let mut out = out.lock();
        out.write_all(self.string_buffer.as_bytes()).unwrap();
        self.string_buffer.clear();
    }
}

fn create_cout(capacity: usize) -> CharacterOutput {
    CharacterOutput {
        string_buffer: String::with_capacity(capacity),
    }
}

// ------------------------------------------------------------------------

trait StepSum: Iterator {
    fn step_sum(&mut self, step: usize) -> u32;
}

impl<I: Iterator> StepSum for I where I: Iterator<Item = u32> {
    fn step_sum(&mut self, step: usize) -> u32 {
        let mut acc;

        match self.next() {
            Some(value) => acc = value,
            None => return 0
        }

        loop {
            match self.nth(step - 1) {
                Some(value) => acc += value,
                None => break
            }
        }

        acc
    }
}

fn main() {
    let cin = stdin();
    let cin = &mut create_cin(cin.lock(), 32);

    let n = cin.scan_u(LF) as usize;
    let a = cin.scan_u_vec(n, SP, LF);

    let total_rainfall = a.iter().sum::<u32>();
    let first_x = total_rainfall - 2 * a.iter().skip(1).map(|&v| v).step_sum(2);
    let mut rest_x_iterator = a.iter().take(n - 1).scan(first_x, |x, a| {
        *x = 2 * a - *x;
        Some(*x)
    });

    let cout = &mut create_cout(11 * n);
    cout.add(first_x, ' ');
    cout.add_from_iterator(&mut rest_x_iterator, n - 1, ' ', '\n');
    cout.flush();
}


#![allow(unused_mut)]
#![allow(non_snake_case)]
#![allow(unused_variables)]
#![allow(unused_imports)]
#![allow(unused_macros)]
#![allow(dead_code)]
// https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        let mut next = || { iter.next().unwrap() };
        input_inner!{next, $($r)*}
    };
    ($($r:tt)*) => {
        let stdin = std::io::stdin();
        let mut bytes = std::io::Read::bytes(std::io::BufReader::new(stdin.lock()));
        let mut next = move || -> String{
            bytes
                .by_ref()
                .map(|r|r.unwrap() as char)
                .skip_while(|c|c.is_whitespace())
                .take_while(|c|!c.is_whitespace())
                .collect()
        };
        input_inner!{next, $($r)*}
    };
}

macro_rules! input_inner {
    ($next:expr) => {};
    ($next:expr, ) => {};

    ($next:expr, $var:ident : $t:tt $($r:tt)*) => {
        let mut $var = read_value!($next, $t);
        input_inner!{$next $($r)*}
    };
}

macro_rules! read_value {
    ($next:expr, ( $($t:tt),* )) => {
        ( $(read_value!($next, $t)),* )
    };

    ($next:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()
    };

    ($next:expr, chars) => {
        read_value!($next, String).chars().collect::<Vec<char>>()
    };

    ($next:expr, usize1) => {
        read_value!($next, usize) - 1
    };

    ($next:expr, $t:ty) => {
        $next().parse::<$t>().expect("Parse error")
    };
}

macro_rules! max {
    ($x: expr) => ($x);
    ($x: expr, $($y: expr),+) => {
        cmp::max($x, max!($($y),+))
    };
}

macro_rules! min {
    ($x: expr) => ($x);
    ($x: expr, $($y: expr),+) => {
        cmp::min($x, min!($($y),+))
    };
}

macro_rules! abs {
    ($x:expr, $y:expr) => {
        cmp::max($x, $y) - cmp::min($x, $y)
    };
}

const MOD: usize = 1_000_000_007;

struct BinCoeff {
    size: usize,
    fac: Vec<usize>,
    finv: Vec<usize>,
    inv: Vec<usize>,
}

impl BinCoeff {
    fn new(size: usize) -> BinCoeff {
        let fac = vec![0; size];
        let finv = vec![0; size];
        let inv = vec![0; size];
        let mut bincoeff = BinCoeff {
            size,
            fac: fac,
            finv: finv,
            inv: inv,
        };
        bincoeff.com_init();
        bincoeff
    }

    fn com_init(&mut self) {
        let fac = &mut self.fac;
        let finv = &mut self.finv;
        let inv = &mut self.inv;
        let size = self.size;
        fac[0] = 1;
        fac[1] = 1;
        finv[0] = 1;
        finv[1] = 1;
        inv[1] = 1;
        for i in 2..size {
            fac[i] = fac[i - 1] * i % MOD;
            inv[i] = MOD - inv[MOD % i] * (MOD / i) % MOD;
            finv[i] = finv[i - 1] * inv[i] % MOD;
        }
    }

    fn bin_coeff(&mut self, n: usize, k: usize) -> usize {
        if k > n / 2 {
            self.bin_coeff(n, n - k)
        } else {
            self.fac[n] * (self.finv[k] * self.finv[n - k] % MOD) % MOD
        }
    }
}

struct UnionFind {
    par: Vec<usize>,
}

impl UnionFind {
    fn new(size: usize) -> UnionFind {
        UnionFind {
            par: (0..size).collect::<Vec<usize>>(),
        }
    }

    fn root(&mut self, node: usize) -> usize {
        let parent = self.par[node];
        if parent == node {
            parent
        } else {
            let parent = self.root(parent);
            self.par[node] = parent;
            parent
        }
    }

    fn unite(&mut self, a: usize, b: usize) {
        let root_a = self.root(a);
        let root_b = self.root(b);
        self.par[root_b] = root_a;
    }

    fn is_same(&mut self, a: usize, b: usize) -> bool {
        let root_a = self.root(a);
        let root_b = self.root(b);
        root_a == root_b
    }
}

// must input n <= m
fn gcd(n: usize, m: usize) -> usize {
    if n == 0 {
        m
    } else {
        gcd(m % n, n)
    }
}

fn printer<T, U>(mut array: T)
where
    T: Iterator<Item = U>,
    U: fmt::Display + Copy,
{
    if let Some(a) = array.next() {
        print!("{}", a);
    }
    for a in array {
        print!(" {}", a);
    }
    println!()
}

fn sieve_of_eratosthenes(max: usize) -> Vec<bool> {
    let mut candidates = vec![true; max + 1];
    candidates[0] = false;
    candidates[1] = false;
    let mut num = 2;
    while num * num <= max {
        if candidates[num] {
            let prime = num;
            for n in 2..max / prime + 1 {
                candidates[prime * n] = false;
            }
        }
        num += 1;
    }
    candidates
}

use std::cmp::Ordering;
use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque};
use std::io::{self, BufRead, Read};
use std::{cmp, fmt, iter, usize};

fn main() {
    input! {
        N: usize,
        A: [usize; N],
    }
    let A: Vec<usize> = A;
    let mut water = vec![0usize; N];
    let min = *A.iter().min().unwrap();
    let min_ind = A.iter().position(|x| *x == min).unwrap();

    let mut current_value = 0;
    'outer: for i in (0..=min).rev() {
        current_value = i;
        for aa in A.iter().cycle().skip(min_ind).take(N) {
            if *aa >= current_value {
                current_value = *aa - current_value;
            } else {
                continue 'outer;
            }
        }

        if current_value == i {
            break 'outer;
        }
    }

    for ind in (0..N).cycle().skip(min_ind).take(N) {
        water[ind] = 2 * current_value;
        current_value = A[ind] - current_value;
    }

    for w in water {
        println!("{}", w);
    }
}


#![allow(unused_mut)]
#![allow(non_snake_case)]
#![allow(unused_variables)]
#![allow(unused_imports)]
#![allow(unused_macros)]
#![allow(dead_code)]
// https://qiita.com/tanakh/items/0ba42c7ca36cd29d0ac8
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        let mut next = || { iter.next().unwrap() };
        input_inner!{next, $($r)*}
    };
    ($($r:tt)*) => {
        let stdin = std::io::stdin();
        let mut bytes = std::io::Read::bytes(std::io::BufReader::new(stdin.lock()));
        let mut next = move || -> String{
            bytes
                .by_ref()
                .map(|r|r.unwrap() as char)
                .skip_while(|c|c.is_whitespace())
                .take_while(|c|!c.is_whitespace())
                .collect()
        };
        input_inner!{next, $($r)*}
    };
}

macro_rules! input_inner {
    ($next:expr) => {};
    ($next:expr, ) => {};

    ($next:expr, $var:ident : $t:tt $($r:tt)*) => {
        let mut $var = read_value!($next, $t);
        input_inner!{$next $($r)*}
    };
}

macro_rules! read_value {
    ($next:expr, ( $($t:tt),* )) => {
        ( $(read_value!($next, $t)),* )
    };

    ($next:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()
    };

    ($next:expr, chars) => {
        read_value!($next, String).chars().collect::<Vec<char>>()
    };

    ($next:expr, usize1) => {
        read_value!($next, usize) - 1
    };

    ($next:expr, $t:ty) => {
        $next().parse::<$t>().expect("Parse error")
    };
}

macro_rules! max {
    ($x: expr) => ($x);
    ($x: expr, $($y: expr),+) => {
        cmp::max($x, max!($($y),+))
    };
}

macro_rules! min {
    ($x: expr) => ($x);
    ($x: expr, $($y: expr),+) => {
        cmp::min($x, min!($($y),+))
    };
}

macro_rules! abs {
    ($x:expr, $y:expr) => {
        cmp::max($x, $y) - cmp::min($x, $y)
    };
}

const MOD: usize = 1_000_000_007;

struct BinCoeff {
    size: usize,
    fac: Vec<usize>,
    finv: Vec<usize>,
    inv: Vec<usize>,
}

impl BinCoeff {
    fn new(size: usize) -> BinCoeff {
        let fac = vec![0; size];
        let finv = vec![0; size];
        let inv = vec![0; size];
        let mut bincoeff = BinCoeff {
            size,
            fac: fac,
            finv: finv,
            inv: inv,
        };
        bincoeff.com_init();
        bincoeff
    }

    fn com_init(&mut self) {
        let fac = &mut self.fac;
        let finv = &mut self.finv;
        let inv = &mut self.inv;
        let size = self.size;
        fac[0] = 1;
        fac[1] = 1;
        finv[0] = 1;
        finv[1] = 1;
        inv[1] = 1;
        for i in 2..size {
            fac[i] = fac[i - 1] * i % MOD;
            inv[i] = MOD - inv[MOD % i] * (MOD / i) % MOD;
            finv[i] = finv[i - 1] * inv[i] % MOD;
        }
    }

    fn bin_coeff(&mut self, n: usize, k: usize) -> usize {
        if k > n / 2 {
            self.bin_coeff(n, n - k)
        } else {
            self.fac[n] * (self.finv[k] * self.finv[n - k] % MOD) % MOD
        }
    }
}

struct UnionFind {
    par: Vec<usize>,
}

impl UnionFind {
    fn new(size: usize) -> UnionFind {
        UnionFind {
            par: (0..size).collect::<Vec<usize>>(),
        }
    }

    fn root(&mut self, node: usize) -> usize {
        let parent = self.par[node];
        if parent == node {
            parent
        } else {
            let parent = self.root(parent);
            self.par[node] = parent;
            parent
        }
    }

    fn unite(&mut self, a: usize, b: usize) {
        let root_a = self.root(a);
        let root_b = self.root(b);
        self.par[root_b] = root_a;
    }

    fn is_same(&mut self, a: usize, b: usize) -> bool {
        let root_a = self.root(a);
        let root_b = self.root(b);
        root_a == root_b
    }
}

// must input n <= m
fn gcd(n: usize, m: usize) -> usize {
    if n == 0 {
        m
    } else {
        gcd(m % n, n)
    }
}

fn printer<T, U>(mut array: T)
where
    T: Iterator<Item = U>,
    U: fmt::Display + Copy,
{
    if let Some(a) = array.next() {
        print!("{}", a);
    }
    for a in array {
        print!(" {}", a);
    }
    println!()
}

fn sieve_of_eratosthenes(max: usize) -> Vec<bool> {
    let mut candidates = vec![true; max + 1];
    candidates[0] = false;
    candidates[1] = false;
    let mut num = 2;
    while num * num <= max {
        if candidates[num] {
            let prime = num;
            for n in 2..max / prime + 1 {
                candidates[prime * n] = false;
            }
        }
        num += 1;
    }
    candidates
}

use std::cmp::Ordering;
use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque};
use std::io::{self, BufRead, Read};
use std::{cmp, fmt, iter, usize};

fn main() {
    input! {
        N: usize,
        A: [usize; N],
    }
    let A: Vec<usize> = A;
    let mut water = vec![0usize; N];
    let min = A.iter().min().unwrap().clone();
    let min_ind = A.iter().position(|x| *x == min).unwrap();

    let mut current_value = 0;
    'outer: for i in (0..=min).rev() {
        current_value = i;
        for &aa in A.iter().cycle().skip(min_ind).take(N) {
            if aa >= current_value {
                current_value = aa - current_value;
            } else {
                continue 'outer;
            }
        }

        if current_value == i {
            break 'outer;
        }
    }

    for ind in (0..N).cycle().skip(min_ind).take(N) {
        water[ind] = 2 * current_value;
        current_value = A[ind] - current_value;
    }

    for w in water {
        println!("{}", w);
    }
}


use std::io::BufRead;

fn main() {
    let mut input = String::new();
    let stdin = std::io::stdin();
    let mut handle = stdin.lock();
    handle.read_line(&mut input).unwrap();
    let mut an: Vec<u32> = handle
        .split(b' ')
        .map(|n| {
            n.unwrap()
                .iter()
                .map(|n| *n as char)
                .collect::<String>()
                .parse()
                .unwrap()
        })
        .collect::<Vec<_>>();
    let mut mn = an.iter().fold(0, |acc, n| n - acc);
    print!("{}", mn);
    an.pop();
    for a in an.iter() {
        mn = 2 * a - mn;
        print!(" {}", mn)
    }
}


import Foundation

extension String {

    func toStrList() -> [String] {
        return self.map{String($0)}
    }

    func toIntList() -> [Int] {
        return self.map{Int(String($0))!}
    }

    func toSepDoubleList() -> [Double]{
        return self.split(separator: " ").map{Double($0)!}
    }

    func toSepIntList() -> [Int] {
        return self.split(separator: " ").map{Int($0)!}
    }

    func toSepStrList() -> [String] {
        return self.split(separator: " ").map{String($0)}
    }

    func zFill(n:Int) -> String {
        return String(format: "%0\(n)d", Int(self)!)
    }

    func count(c:Character) -> Int{
        var result = 0

        for e in self{
            if e == c{
                result += 1
            }
        }
        return result
    }

    func counter() -> Dictionary<Character, Int>{
        var result:[Character:Int] = [:]

        for c in self{
            guard let _ = result.index(forKey: c) else {
                result[c] = 1
                continue
            }
            result[c]! += 1
        }
        return result
    }
}

extension Int {
    func toBin() -> String {
        return String(self, radix: 2)
    }

    func toNBin(_ radix:Int) -> String{
        return String(self, radix: radix)
    }

    func toD() -> Double {
        return Double(self)
    }
}

extension Double {
    func toI() -> Int {
        return Int(self)
    }
}

extension Array where Element: Equatable{
    func count(n:Self.Element) -> Int{
        var result = 0
        for e in self{
            if e == n{
                result += 1
            }
        }
        return result
    }
}

extension Array {
    func dump(){
        for x in 0..<self.count-1{
            print(self[x], terminator: " ")
        }
        print(self.last!)
    }
}

func pow(_ base:Int,_ exp:Int) -> Int{
    let d = pow(base.toD(), exp.toD())
    return Int(d)
}

func distance(p1:CGPoint, p2:CGPoint) -> Double {
    let diffp = CGPoint(x:p1.x - p2.x, y:p1.y - p2.y)
    return Double(sqrt(diffp.x*diffp.x + diffp.y * diffp.y))
}

func distance(p1:[Double], p2:[Double]) -> Double{
    let diff = [p1[0] - p2[0], p1[1] - p2[1]]
    return sqrt(diff[0] * diff[0] + diff[1] * diff[1])

}

func lotate(theta:Double, point:[Double]) -> [Double] {
    let matrix = [
        [cos(theta), -sin(theta)],
        [sin(theta), cos(theta)]
    ]
    let x = point[0]
    let y = point[1]

    let rx = matrix[0][0]*x + matrix[0][1]*y
    let ry = matrix[1][0]*x + matrix[1][1]*y

    return [rx, ry]
}

func abc133c(){
    let N = Int(readLine()!)!
    let A = readLine()!.toSepIntList()
    var X = Array(repeating: 0, count: N)
    let total = A.reduce(0, +)
    var sum = 0
    for i in stride(from: 1, to: N, by: 2){
        sum += A[i]
    }
    X[0] = total - 2*sum

    for i in 1..<N {
        X[i] = 2*A[i-1] - X[i-1]
    }
    X.dump()
}

abc133c()


let N = Int(readLine()!)!
let A = readLine()!.characters.split(" ").map{Int(String($0))!}
//let sum = A.reduce(0){$0+$1}
let ans = (0..<N).map{A[($0+N-1)%N] + A[$0] - A[($0+1)%N]}
ans.forEach{print($0, terminator: " ")}
print()


let N = readInt()!
let A = readIntSplit(by: " ")
//let sum = A.reduce(0){$0+$1}
let ans = (0..<N).map{A[($0+N-1)%N] + A[$0] - A[($0+1)%N]}
ans.forEach{print($0, terminator: " ")}
print()


import * as fs from 'fs';

export class Reader {
    lines: string[];
    currentLine: number;

    constructor() {
        this.lines = fs.readFileSync("/dev/stdin", "utf8").trim().split("\n");
        this.currentLine = 0;
    }

    readLine(): string {
        return this.lines[this.currentLine++];
    }

    readInt(): number {
        return Number(this.readLine());
    }

    readInts(): number[] {
        return this.readLine().split(" ").map(Number);
    }
}

let reader: Reader = new Reader();
let N = reader.readInt();
/**
 *
 * D[1]/2+D[2]/2=A[1]
 * D[2]/2+D[3]/2=A[2]
 * D[3]/2+D[1]/2=A[3]
 * D[1]=A[1]-A[2]+A[3]
 *
 */
let A = reader.readInts();
let D: number[] = new Array(N).fill(0);
let S = 0, sign = 1;
for(let i=0; i<N; i++) {
	S += sign*A[i];
	sign = -sign;
}
D[0] = S;
D[N-1] = 2*A[N-1]-D[0]
for(let i=1; i<N-1; i++) {
	D[i] = 2*A[i-1]-D[i-1];
}
console.log(D.map((value) => value.toString()).join(" "));


function main(input) {
  input = input.trim().split("\n");
  const n = Number(input[0]);
  const a = input[1].split(" ").map(n => Number(n));
  const arr = [0];
  for (let i = 1; i < n; i++) {
    const num = a[i-1]*2 - arr[arr.length -1];
    arr.push(num);
  }
  const dif = (a[a.length-1]*2 - (arr[0] + arr[arr.length -1]))/2;
  const result = [dif];
  for (let i = 1; i < n; i++) {
    result.push(a[i-1]*2 - result[result.length -1]);
  }
  console.log(result.join(" "));
}
main(require("fs").readFileSync("/dev/stdin", "utf8"));


export class Main {
  static main(input): string {
    const tmp: string[] = input.split("\n");
    const n: number = parseInt(tmp[0]);
    const a: number[] = tmp[1].split(" ").slice(0, n).map(t => parseInt(t));
    let prevM: number = 0;
    let t: number = 1;
    for (let i = 0; i < n; ++i) {
      prevM += t * a[i];
      t *= -1;
    }
    const result: number[] = [];
    result.push(prevM);
    for (let i = 0; i < n - 1; ++i) {
      const m: number = (a[i] - prevM / 2) * 2;
      result.push(m);
      prevM = m;
    }
    return `${result.join(" ")}`;
  }
}
console.log(Main.main(require("fs").readFileSync("/dev/stdin", "utf8")));


function main(input) {
  input = input.trim().split("\n");
  const n = Number(input[0]);
  const a = input[1].split(" ").map(n => Number(n));
  const arr = [0];
  for (let i = 1; i < n; i++) {
    const num = a[i] - arr[arr.length -1];
    arr.push(num);
  }
  const dif = a[a.length-1]*2 - (arr[0] + arr[arr.length -1]);
  const result = arr.map(num => num + (dif/2));
  console.log(result.join(" "));
}
main(require("fs").readFileSync("/dev/stdin", "utf8"));


N = int(input())
S = input()
ans = 1
for c in [chr(ord('a') + i) for i in range(26)]:
    ans = (ans * (S.count(c) + 1)) % (10**9 + 7)
ans = (ans - 1) % (10**9 + 7)
print(ans)


import sys
input = sys.stdin.readline

def main():
	N = int(input())
	S = input().rstrip()
	M = 10**9 + 7

	# a     (0)+1
	# ab    (1)+1+1
	# abc   (3)+3+1
	# abca  (7)+1+2+1
	# abcab (11)+1+3+2
	# abcabc (17)+1+4+3
	A = ord("a")
	res = 1
	for i in range(26):
		q = chr(i+A)
		qc = S.count(q)
		res = res * (qc+1) % M

	print((res-1) % M)

main()


n=int(input())
S=input()
a='abcdefghijklmnopqrstuvwxyz'
ans=1
for i in range(26):
  cnt=S.count(a[i])
  ans=ans*(cnt+1)
ans-=1
ans=ans%(10**9+7)
print(int(ans))


import sys, math, re
from functools import lru_cache
sys.setrecursionlimit(10**9)
import numpy as np
MOD = 10**9+7

def input():
    return sys.stdin.readline()[:-1]

def mi():
    return map(int, input().split())

def ii():
    return int(input())

def i2(n):
    tmp = [list(mi()) for i in range(n)]
    return [list(i) for i in zip(*tmp)]

def main():
    N = ii()
    S = input()
    d = {}
    for i in range(N):
        if not S[i] in d:
            d[S[i]] = 1
        d[S[i]] += 1

    a = np.array(list(d.values()))
    ans = np.multiply.reduce(a)-1
    print(ans)

if __name__ == "__main__":
    main()


n = int(input())
s = input()
dic = {}
for si in s:
  if si not in dic:
    dic[si] = 0
  dic[si] += 1
ans = 1
for k, v in dic.items():
  ans *= (v+1)
print(ans-1)


from collections import defaultdict
N = int(input())
S = input()

mod = 10**9+7
char_done = defaultdict(int)
# dp[i] := 左から0文字目(1-idx)まで見たときの答え
# 一旦空文字列も含む
dp = [0] * (N+1)
dp[0] = 1
for i in range(1,N+1):
    #print(i,'---')
    if char_done[S[i-1]] == 0:
        #print("not done",dp[i-1])
        dp[i] = 2*dp[i-1]
    else:
        dp[i] = dp[i-1]//2 + dp[i-1]

    #print(dp[i])
    dp[i] %= mod
    char_done[S[i-1]] = 1

print((dp[-1]-1)%mod)


import java.io.*;
import java.util.*;

public class Main {
    static long mod = 1000000007;
    public static void main(String args[]) throws IOException {
        int[] freq = new int[26];
        Scan sc= new Scan();
        int n = sc.scanInt();
        for(int i= 0; i < n; ++i){
            char curr = (char)sc.scan();
            freq[curr-'a']++;
        }
        long res = 1;
        for(int i = 0; i < 26; ++i){
            res = modMul(res, freq[i]+1);
        }
        System.out.println(res-1);
    }

    static long modMul(long a, long b){
        return (a*b)%mod;
    }
}

class Scan
{
    private byte[] buf=new byte[1024];
    private int index;
    private InputStream in;
    private int total;
    public Scan()
    {
        in=System.in;
    }
    public int scan()throws IOException
    {
        if(total<0)
        throw new InputMismatchException();
        if(index>=total)
        {
            index=0;
            total=in.read(buf);
            if(total<=0)
            return -1;
        }
        return buf[index++];
    }
    public int scanInt()throws IOException
    {
        int integer=0;
        int n=scan();
        while(isWhiteSpace(n))
        n=scan();
        int neg=1;
        if(n=='-')
        {
            neg=-1;
            n=scan();
        }
        while(!isWhiteSpace(n))
        {
            if(n>='0'&&n<='9')
            {
                integer*=10;
                integer+=n-'0';
                n=scan();
            }
            else throw new InputMismatchException();
        }
        return neg*integer;
    }
    public long scanLong() throws IOException {
        long integer=0;
        int n=scan();
        while(isWhiteSpace(n))
        n=scan();
        int neg=1;
        if(n=='-')
        {
            neg=-1;
            n=scan();
        }
        while(!isWhiteSpace(n))
        {
            if(n>='0'&&n<='9')
            {
                integer*=10;
                integer+=n-'0';
                n=scan();
            }
            else throw new InputMismatchException();
        }
        return neg*integer;
    }
    public double scanDouble()throws IOException
    {
        double doub=0;
        int n=scan();
        while(isWhiteSpace(n))
        n=scan();
        int neg=1;
        if(n=='-')
        {
            neg=-1;
            n=scan();
        }
        while(!isWhiteSpace(n)&&n!='.')
        {
            if(n>='0'&&n<='9')
            {
                doub*=10;
                doub+=n-'0';
                n=scan();
            }
            else throw new InputMismatchException();
        }
        if(n=='.')
        {
            n=scan();
            double temp=1;
            while(!isWhiteSpace(n))
            {
                if(n>='0'&&n<='9')
                {
                    temp/=10;
                    doub+=(n-'0')*temp;
                    n=scan();
                }
                else throw new InputMismatchException();
            }
        }
        return doub*neg;
    }
    public String scanString()throws IOException
    {
        StringBuilder sb=new StringBuilder();
        int n=scan();
        while(isWhiteSpace(n))
        n=scan();
        while(!isWhiteSpace(n))
        {
            sb.append((char)n);
            n=scan();
        }
        return sb.toString();
    }
    private boolean isWhiteSpace(int n)
    {
        if(n==' '||n=='\n'||n=='\r'||n=='\t'||n==-1)
        return true;
        return false;
    }
}


import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class Main {
	static InputStream is;
	static PrintWriter out;
	static String INPUT = "";

	static void solve()
	{
		int n = ni();
		char[] s = ns(n);
		int[] f = new int[26];
		int mod = 1000000007;
		for(char c : s){
			f[c-'a']++;
		}
		long ans = 1;
		for(int i = 0;i < 26;i++){
			ans = ans * (f[i] + 1) % mod;
		}
		out.println((ans+mod-1)%mod);
	}

	public static long[] enumPows(int a, int n, int mod)
	{
		a %= mod;
		long[] pows = new long[n+1];
		pows[0] = 1;
		for(int i = 1;i <= n;i++)pows[i] = pows[i-1] * a % mod;
		return pows;
	}

	public static void main(String[] args) throws Exception
	{
		long S = System.currentTimeMillis();
		is = INPUT.isEmpty() ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		solve();
		out.flush();
		long G = System.currentTimeMillis();
		tr(G-S+"ms");
	}

	private static boolean eof()
	{
		if(lenbuf == -1)return true;
		int lptr = ptrbuf;
		while(lptr < lenbuf)if(!isSpaceChar(inbuf[lptr++]))return false;

		try {
			is.mark(1000);
			while(true){
				int b = is.read();
				if(b == -1){
					is.reset();
					return true;
				}else if(!isSpaceChar(b)){
					is.reset();
					return false;
				}
			}
		} catch (IOException e) {
			return true;
		}
	}

	private static byte[] inbuf = new byte[1024];
	static int lenbuf = 0, ptrbuf = 0;

	private static int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private static boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
//	private static boolean isSpaceChar(int c) { return !(c >= 32 && c <= 126); }
	private static int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private static double nd() { return Double.parseDouble(ns()); }
	private static char nc() { return (char)skip(); }

	private static String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private static char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private static char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private static int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private static int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private static long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private static void tr(Object... o) { if(INPUT.length() != 0)System.out.println(Arrays.deepToString(o)); }
}


import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.Arrays;

public class Main {
    public static void main(String[] args) throws Exception {
        boolean local = false;
        boolean async = false;

        Charset charset = Charset.forName("ascii");

        FastIO io = local ? new FastIO(new FileInputStream("D:\\DATABASE\\TESTCASE\\Code.in"), System.out, charset) : new FastIO(System.in, System.out, charset);
        Task task = new Task(io, new Debug(local));

        if (async) {
            Thread t = new Thread(null, task, "dalt", 1 << 27);
            t.setPriority(Thread.MAX_PRIORITY);
            t.start();
            t.join();
        } else {
            task.run();
        }

        if (local) {
            io.cache.append("\n\n--memory -- \n" + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) >> 20) + "M");
        }

        io.flush();
    }

    public static class Task implements Runnable {
        final FastIO io;
        final Debug debug;
        int inf = (int) 1e8;
        int mod = (int) 1e9 + 7;

        public int mod(int val) {
            val %= mod;
            if (val < 0) {
                val += mod;
            }
            return val;
        }

        public int mod(long val) {
            val %= mod;
            if (val < 0) {
                val += mod;
            }
            return (int) val;
        }

        int bitAt(int x, int i) {
            return (x >> i) & 1;
        }

        int bitAt(long x, int i) {
            return (int) ((x >> i) & 1);
        }

        public Task(FastIO io, Debug debug) {
            this.io = io;
            this.debug = debug;
        }

        @Override
        public void run() {
            solve();
        }

        public void solve() {
            int n = io.readInt();
            char[] data = new char[n];
            io.readString(data, 0);
            int[] count = new int[128];
            for (char c : data) {
                count[c]++;
            }

            int sum = 1;
            for (int i = 'a'; i <= 'z'; i++) {
                sum = mod((long) sum * (count[i] + 1));
            }
            sum = mod(sum - 1);
            io.cache.append(sum);
        }
    }

    public static class FastIO {
        public final StringBuilder cache = new StringBuilder();
        private final InputStream is;
        private final OutputStream os;
        private final Charset charset;
        private StringBuilder defaultStringBuf = new StringBuilder(1 << 8);
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastIO(InputStream is, OutputStream os, Charset charset) {
            this.is = is;
            this.os = os;
            this.charset = charset;
        }

        public FastIO(InputStream is, OutputStream os) {
            this(is, os, Charset.forName("ascii"));
        }

        private int read() {
            while (bufLen == bufOffset) {
                bufOffset = 0;
                try {
                    bufLen = is.read(buf);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                if (bufLen == -1) {
                    return -1;
                }
            }
            return buf[bufOffset++];
        }

        public void skipBlank() {
            while (next >= 0 && next <= 32) {
                next = read();
            }
        }

        public int readInt() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            int val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

        public long readLong() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            long val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

        public double readDouble() {
            boolean sign = true;
            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+';
                next = read();
            }

            long val = 0;
            while (next >= '0' && next <= '9') {
                val = val * 10 + next - '0';
                next = read();
            }
            if (next != '.') {
                return sign ? val : -val;
            }
            next = read();
            long radix = 1;
            long point = 0;
            while (next >= '0' && next <= '9') {
                point = point * 10 + next - '0';
                radix = radix * 10;
                next = read();
            }
            double result = val + (double) point / radix;
            return sign ? result : -result;
        }

        public String readString(StringBuilder builder) {
            skipBlank();

            while (next > 32) {
                builder.append((char) next);
                next = read();
            }

            return builder.toString();
        }

        public String readString() {
            defaultStringBuf.setLength(0);
            return readString(defaultStringBuf);
        }

        public int readLine(char[] data, int offset) {
            int originalOffset = offset;
            while (next != -1 && next != '\n') {
                data[offset++] = (char) next;
                next = read();
            }
            return offset - originalOffset;
        }

        public int readString(char[] data, int offset) {
            skipBlank();

            int originalOffset = offset;
            while (next > 32) {
                data[offset++] = (char) next;
                next = read();
            }

            return offset - originalOffset;
        }

        public int readString(byte[] data, int offset) {
            skipBlank();

            int originalOffset = offset;
            while (next > 32) {
                data[offset++] = (byte) next;
                next = read();
            }

            return offset - originalOffset;
        }

        public char readChar() {
            skipBlank();
            char c = (char) next;
            next = read();
            return c;
        }

        public void flush() {
            try {
                os.write(cache.toString().getBytes(charset));
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        public boolean hasMore() {
            skipBlank();
            return next != -1;
        }
    }

    public static class Debug {
        private boolean allowDebug;

        public Debug(boolean allowDebug) {
            this.allowDebug = allowDebug;
        }

        public void assertTrue(boolean flag) {
            if (!allowDebug) {
                return;
            }
            if (!flag) {
                fail();
            }
        }

        public void fail() {
            throw new RuntimeException();
        }

        public void assertFalse(boolean flag) {
            if (!allowDebug) {
                return;
            }
            if (flag) {
                fail();
            }
        }

        private void outputName(String name) {
            System.out.print(name + " = ");
        }

        public void debug(String name, int x) {
            if (!allowDebug) {
                return;
            }

            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, long x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, double x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, int[] x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.toString(x));
        }

        public void debug(String name, long[] x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.toString(x));
        }

        public void debug(String name, double[] x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.toString(x));
        }

        public void debug(String name, Object x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, Object... x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.deepToString(x));
        }
    }
}


import java.util.Scanner;

public class Main {

	static Scanner scanner;
	public static void main(String[] args) {
	    scanner = new Scanner(System.in);

	    long N=gi();
	    String S= gs();
	    int[] K=new int[26];
	    for(int i=0;i<N;i++) {
	    	char c=S.charAt(i);
	    	K[c-97]++;
	    }
	    int a=1;
	    for(int i=0;i<K.length;i++) {
	    	if(K[i]==0) continue;
	    	a*=K[i]+1;
	    	a=a%1000000007;
	    }
	    a=(a+1000000006)%1000000007;
//	    if (k>k2) {
//	    	System.out.println("NO");
//	    } else {
//	    	System.out.println("YES");
//	    }
	    System.out.println(a);
	}

	// 文字列として入力を取得
	public static String gs() {
		return scanner.next();
	}

	// intとして入力を取得
	public static int gi() {
		return Integer.parseInt(scanner.next());
	}

	// longとして入力を取得
	public static long gl() {
		return Long.parseLong(scanner.next());
	}

	// doubleとして入力を取得
	public static double gd() {
		return Double.parseDouble(scanner.next());
	}
}