Ivan has an array consisting of n elements. Each of the elements is an integer from 1 to n.

Recently Ivan learned about permutations and their lexicographical order. Now he wants to change (replace) minimum number of elements in his array in such a way that his array becomes a permutation (i.e. each of the integers from 1 to n was encountered in his array exactly once). If there are multiple ways to do it he wants to find the lexicographically minimal permutation among them.

Thus minimizing the number of changes has the first priority, lexicographical minimizing has the second priority.

In order to determine which of the two permutations is lexicographically smaller, we compare their first elements. If they are equal — compare the second, and so on. If we have two permutations x and y, then x is lexicographically smaller if xi < yi, where i is the first index in which the permutations x and y differ.

Determine the array Ivan will obtain after performing all the changes.

Input

The first line contains an single integer n (2 ≤ n ≤ 200 000) — the number of elements in Ivan's array.

The second line contains a sequence of integers a1, a2, ..., an (1 ≤ ai ≤ n) — the description of Ivan's array.

Output

In the first line print q — the minimum number of elements that need to be changed in Ivan's array in order to make his array a permutation. In the second line, print the lexicographically minimal permutation which can be obtained from array with q changes.

Examples

Input

4
3 2 2 3


Output

2
1 2 4 3 


Input

6
4 5 6 3 2 1


Output

0
4 5 6 3 2 1 


Input

10
6 8 4 6 7 1 6 3 4 5


Output

3
2 8 4 6 7 1 9 3 10 5 

Note

In the first example Ivan needs to replace number three in position 1 with number one, and number two in position 3 with number four. Then he will get a permutation [1, 2, 4, 3] with only two changed numbers — this permutation is lexicographically minimal among all suitable. 

In the second example Ivan does not need to change anything because his array already is a permutation.
import java.io.*;
import java.util.*;
import java.math.*;
import java.util.concurrent.SynchronousQueue;

public class graph_basics{
	public static final long mod =  1000000007;
	public static ArrayList<Integer>[] graph;
	public static InputReader in;
	public static PrintWriter w;
	static Edge edge[]; // collection of all edges
	static int level[],parent[],rank[],cost[];
	public static boolean vis[];
	public static HashMap<pair,Boolean> evis=new HashMap<pair,Boolean>();
	public static HashMap<pair,Integer> edges=new HashMap<pair,Integer>();
	public static HashSet<Integer> ans=new HashSet<Integer>();
	static int V=0,E=0,count=0;
	static String str;
	static char[][] arr;
	@SuppressWarnings("unchecked")
	public static void main(String[] args) {
		new Thread(null, new Runnable() {
			public void run() {
				try{
					solve();
					w.flush();
					w.close();
				}
				catch(Exception e){
					e.printStackTrace();
				}
			}
		}, "1", 1 << 26).start();
	}
	static ArrayList<Integer> topo;
	static int bit1[],bit2[];
	static int max_len,maxi;
	static void solve(){
		in = new InputReader(System.in);
		w = new PrintWriter(System.out);
		int n=in.nextInt();
        int a[]=in.nextIntArray(n);
        HashMap<Integer,Integer> hm=new HashMap();
        for(int i=1;i<=n;i++)
        {
                hm.put(i,0);
        }
        int tot[]=new int[n+1];
        
        for(int i=0;i<n;i++)
        {
                tot[a[i]]++;
                if(!hm.containsKey(a[i]))
                        hm.put(a[i],1);
                else
                        hm.put(a[i],hm.get(a[i])+1);
        }

        int ans=0;
        int rem[]=new int[n+1];
        Queue<Integer> Q=new LinkedList();
        for(int i=1;i<=n;i++)
        {
                
                if(hm.get(i)==0)
                {
                        Q.add(i);
                        ans++;
                }
                else if(hm.get(i)>1)
                {
                        rem[i]+=(hm.get(i)-1);
                }
        }
        
        w.println(ans);
        int frs[]=new int[n+1];
        int b[]=Arrays.copyOf(a,n);
        for(int i=0;i<n;i++)
        {
                frs[a[i]]++;
                if(rem[a[i]]>0&&a[i]>Q.peek())
                {
                        b[i]=Q.poll();
                        rem[a[i]]--;
                }
                else if(rem[a[i]]>0&&a[i]<Q.peek())
                {
                        int x=tot[a[i]]-frs[a[i]];
                        if(x>=rem[a[i]])
                                continue;
                        else
                        {
                                b[i]=Q.poll();
                                rem[a[i]]--;
                        }
                }
                
        }
        for(int i=0;i<n;i++)
                w.print(b[i]+" ");


	}
	static class pair{
		int i,j;
		public pair(int type,int l){
			this.i=type;
			this.j=l;
		}
	}
	
	static long getSum(long BITree[], int index)
	{
		long sum = 0; // Initialize result

		// index in BITree[] is 1 more than the index in arr[]
		index = index + 1;

		// Traverse ancestors of BITree[index]
		while (index>0)
		{
			// Add current element of BITree to sum
			sum += BITree[index];

			// Move index to parent node in getSum View
			index -= index & (-index);
		}
		return sum;
	}

	// Updates a node in Binary Index Tree (BITree) at given
	// index in BITree.  The given value 'val' is added to
	// BITree[i] and all of its ancestors in tree.
	static void updateBIT(long BITree[], int n, int index, long val)
	{
		// index in BITree[] is 1 more than the index in arr[]
		index = index + 1;

		// Traverse all ancestors and add 'val'
		while (index <= n)
		{
			// Add 'val' to current node of BI Tree
			BITree[index] += val;

			// Update index to that of parent in update View
			index += index & (-index);
		}
	}

	// Returns the sum of array from [0, x]
	static long sum(int x, long BITTree1[], long BITTree2[])
	{
		return (getSum(BITTree1, x) * x) - getSum(BITTree2, x);
	}


	static void updateRange(long BITTree1[], long BITTree2[], int n,
			long val, int l, int r)
	{
		// Update Both the Binary Index Trees
		// As discussed in the article

		// Update BIT1
		updateBIT(BITTree1,n,l,val);
		updateBIT(BITTree1,n,r+1,-val);

		// Update BIT2
		updateBIT(BITTree2,n,l,val*(l-1));
		updateBIT(BITTree2,n,r+1,-val*r);
	}

	static long rangeSum(int l, int r, long BITTree1[], long BITTree2[])
	{
		// Find sum from [0,r] then subtract sum
		// from [0,l-1] in order to find sum from
		// [l,r]
		return sum(r, BITTree1, BITTree2) -
				sum(l-1, BITTree1, BITTree2);
	}


	static long[] constructBITree(int n,int val)
	{
		// Create and initialize BITree[] as 0
		long BITree[] = new long[n+1];
		for (int i=1; i<=n; i++)
			BITree[i] = val;

		return BITree;
	}

	
	static long pow(long x,  long y, long p)
	{
		long res = 1;      // Initialize result

		x = x % p;  // Update x if it is more than or 
		// equal to p

		while (y > 0)
		{
			// If y is odd, multiply x with result
			if (y%2!=0)
				res = (res*x) % p;

			// y must be even now
			y = y>>1; // y = y/2
		x = (x*x) % p;  
		}
		return res;
	}

	static class Pa implements Comparable<Pa>{
		int ind,data;
		public Pa(int ind,int data){
			this.ind=ind;
			this.data=data;
		}
		public int compareTo(Pa that){
			return Integer.compare(this.data, that.data);
		}
	}
	public static void dfs(int cur,int par,int prev){
		vis[cur]=true;
		int cur_len=0;
		for(Integer next:graph[cur]){
			if(cur!=par){
				if(!vis[next]){
					cur_len=prev+1;
					dfs(next,cur,cur_len);
				}	
			}
			if(max_len<cur_len){
				max_len=cur_len;
				maxi=next+1;
			}
			if(max_len==cur_len && maxi<next+1){
				maxi=next+1;
			}
			cur_len=0;
		}
		vis[cur]=false;	
	}
	public static int findSet(int[] P, int[] rank, int x) {
		if (P[x] == x)
			return x;
		return P[x] = findSet(P, rank, P[x]);
	}

	public static void mergeSet(int[] P, int[] rank, int x, int y) {
		int px = findSet(P, rank, x),
				py = findSet(P, rank, y);
		if (rank[px] > rank[py])
			P[py] = px;
		else
			P[px] = py;
		if (rank[px] == rank[py])
			rank[py]++;
	}

	static class Node {
		int u, v, type;

		public Node(int u, int v, int type) {
			this.u = u;
			this.v = v;
			this.type = type;
		}
	}

	static class Edge implements Comparable<Edge>
	{
		int src, dest, weight;

		// Comparator function used for sorting edges based on
		// their weight
		public int compareTo(Edge compareEdge)
		{
			return this.weight-compareEdge.weight;
		}
	};
	static class BIT
	{
		int[] tree;
		int n;
		BIT(int n)
		{
			tree = new int[n+1];
			this.n = n;
		}
		/*
		 * Increases the value at x by v.
		 */
		void upd(int x, int v)
		{
			int i = x;
			while(i<=n)
			{
				tree[i]+=v;
				i += (i&-i);
			}
		}
		/*
		 * Returns the sum of the first x elements.
		 */
		int csum(int x)
		{
			int s = 0;
			while(x>0)
			{
				s += tree[x];
				x -= (x&-x);
			}
			return s;
		}
		/*
		 * Returns the sum of elements x through y, inclusive.
		 */
		int csum(int x, int y)
		{
			return csum(y) - csum(x-1);
		}
		/*
		 * Returns the xth value in the tree.
		 */
		int get(int x)
		{
			int sum = tree[x];
			int z = x - (x&-x);
			x--;
			while(x>z)
			{
				sum -= tree[x];
				x -= (x&-x);
			}
			return sum;
		}
		/*
		 * Multiplies every element in the tree by a.
		 */
		void scale(int a)
		{
			for(int i = 1; i<=n; i++) tree[i] *= a;
		}
	}
	static class InputReader {

		private InputStream stream;
		private byte[] buf = new byte[8192];
		private int curChar, snumChars;
		private SpaceCharFilter filter;

		public InputReader(InputStream stream) {
			this.stream = stream;
		}

		public int snext() {
			if (snumChars == -1)
				throw new InputMismatchException();
			if (curChar >= snumChars) {
				curChar = 0;
				try {
					snumChars = stream.read(buf);
				} catch (IOException e) {
					throw new InputMismatchException();
				}
				if (snumChars <= 0)
					return -1;
			}
			return buf[curChar++];
		}

		public int nextInt() {
			int c = snext();
			while (isSpaceChar(c))
				c = snext();
			int sgn = 1;
			if (c == '-') {
				sgn = -1;
				c = snext();
			}
			int res = 0;
			do {
				if (c < '0' || c > '9')
					throw new InputMismatchException();
				res *= 10;
				res += c - '0';
				c = snext();
			} while (!isSpaceChar(c));
			return res * sgn;
		}

		public long nextLong() {
			int c = snext();
			while (isSpaceChar(c))
				c = snext();
			int sgn = 1;
			if (c == '-') {
				sgn = -1;
				c = snext();
			}
			long res = 0;
			do {
				if (c < '0' || c > '9')
					throw new InputMismatchException();
				res *= 10;
				res += c - '0';
				c = snext();
			} while (!isSpaceChar(c));
			return res * sgn;
		}

		public int[] nextIntArray(int n) {
			int a[] = new int[n];
			for (int i = 0; i < n; i++)
				a[i] = nextInt();
			return a;
		}

		public String readString() {
			int c = snext();
			while (isSpaceChar(c))
				c = snext();
			StringBuilder res = new StringBuilder();
			do {
				res.appendCodePoint(c);
				c = snext();
			} while (!isSpaceChar(c));
			return res.toString();
		}

		public boolean isSpaceChar(int c) {
			if (filter != null)
				return filter.isSpaceChar(c);
			return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
		}

		public interface SpaceCharFilter {
			public boolean isSpaceChar(int ch);
		}
	}
}   