Problem:
Score : 400 points

Problem Statement

We have an H-by-W matrix.
Let a_{ij} be the element at the i-th row from the top and j-th column from the left.
In this matrix, each a_{ij} is a lowercase English letter.

Snuke is creating another H-by-W matrix, A', by freely rearranging the elements in A.
Here, he wants to satisfy the following condition:

Every row and column in A' can be read as a palindrome.

Determine whether he can create a matrix satisfying the condition.

Note

A palindrome is a string that reads the same forward and backward.
For example, a, aa, abba and abcba are all palindromes, while ab, abab and abcda are not.

Constraints

1 ≤ H, W ≤ 100

a_{ij} is a lowercase English letter.

Input

Input is given from Standard Input in the following format:

H W
a_{11}a_{12}...a_{1W}
:
a_{H1}a_{H2}...a_{HW}

Output

If Snuke can create a matrix satisfying the condition, print Yes; otherwise, print No.

Sample Input 1

3 4
aabb
aabb
aacc

Sample Output 1

Yes

For example, the following matrix satisfies the condition.

abba
acca
abba

Sample Input 2

2 2
aa
bb

Sample Output 2

No

It is not possible to create a matrix satisfying the condition, no matter how we rearrange the elements in A.

Sample Input 3

5 1
t
w
e
e
t

Sample Output 3

Yes

For example, the following matrix satisfies the condition.

t
e
w
e
t

Sample Input 4

2 5
abxba
abyba

Sample Output 4

No

Sample Input 5

1 1
z

Sample Output 5

Yes

Solution in Java (OpenJDK 11.0.6) (judge verdict: Accepted)

import java.util.*; import java.io.*; import java.math.*;
public class Main{
	static void solve(){//Here is the main function
  ArrayList<Integer> one1 = nextIntArray();
  int H = one1.get(0);
  int W = one1.get(1);
  HashMap<String, Integer> list = new HashMap<String, Integer>();
  for(int i = 0; i < H; i++){
    ArrayList<String> tmp = nextCharArray();
    for(int j = 0; j < W; j++){
      if(list.containsKey(tmp.get(j))){
      	list.put(tmp.get(j), list.get(tmp.get(j)) + 1);
      }else{
        list.put(tmp.get(j), 1);
      }
    }
  }
  int four = 0;
  int two = 0;
  int one = 0;
  int Hhalf = (H + 1) / 2;
  int Whalf = (W + 1) / 2;
  if(H % 2 == 1 && W % 2 == 1){
    four = (Hhalf - 1) * (Whalf - 1);
    two = (Hhalf - 1) + (Whalf - 1);
    one = 1;
  }else if(H % 2 == 1 && W % 2 != 1){
    four = Whalf * (Hhalf - 1);
    two = Whalf;
  }else if(H % 2 != 1 && W % 2 == 1){
    four = Hhalf * (Whalf - 1);
    two = Hhalf;
  }else{
    four = Hhalf * Whalf;
  }
  
  Iterator<String> it = list.keySet().iterator();
  ArrayList<String> keys = new ArrayList<String>();
  while(it.hasNext()){
  	keys.add(it.next());
  }
  boolean isContain = false;
  while(four > 0){
    for(int i = 0; i < keys.size(); i++){
      if(list.get(keys.get(i)) >= 4){
      	list.put(keys.get(i), list.get(keys.get(i)) - 4);
        four--;
        isContain = true;
      }
    }
    if(isContain){
      isContain = false;
    }else{
      myout("No");
      return;
    }
  }
  while(two > 0){
    for(int i = 0; i < keys.size(); i++){
      if(list.get(keys.get(i)) >= 2){
      	list.put(keys.get(i), list.get(keys.get(i)) - 2);
        two--;
        isContain = true;
      }
    }
    if(isContain){
      isContain = false;
    }else{
      myout("No");
      return;
    }
  }
  while(one > 0){
    for(int i = 0; i < keys.size(); i++){
      if(list.get(keys.get(i)) >= 1){
      	list.put(keys.get(i), list.get(keys.get(i)) - 1);
        one--;
        isContain = true;
      }
    }
    if(isContain){
      isContain = false;
    }else{
      myout("No");
      return;
    }
  }
  
  myout("Yes");
	}
	//Method addition frame start



	//Method addition frame end

	//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------------------------------------------
}