#[allow(unused_macros)]
macro_rules! my_write {
  ($writer:expr, $arg:expr) => {
    $writer.write($arg).unwrap()
  };
  ($writer:expr, $arg:expr,) => {
    my_write!($writer, $arg)
  };
  ($writer:expr, $($arg:expr),+ $(,)?) => {
    {
      let mut buf = Vec::new();
      $(buf.write($arg).unwrap();)+
      $writer.write(&buf).unwrap()
    }
  };
}

use std::io::{ stdin, stdout, Write };

#[inline(always)]
fn each_bit<T, F>(mut n: T, mut func: F)
  where T: Copy +
           PartialEq +
           ::std::ops::Not<Output=T> +
           ::std::ops::BitAnd<Output=T> +
           ::std::ops::BitXor<Output=T> +
           num_traits::identities::Zero +
           num_traits::identities::One +
           num_traits::ops::wrapping::WrappingAdd,
        F: FnMut(T)
{
  loop {
    let tmp = n & (!n).wrapping_add(&T::one());
    if tmp == T::zero() {
      break;
    }
    func(tmp);
    n = n ^ tmp;
  }
}

#[inline(always)]
fn abc173_c() {
  let stdin  = stdin();
  let stdout = stdout();
  let mut scanner = my::Scanner::with_capacity(12, stdin.lock());
  let mut writer  = stdout.lock();
  let mut itoa    = my::ItoA::with_capacity(10);

  let h = my::atoi::<usize>(scanner.read_until(my::SP));
  let w = my::atoi::<usize>(scanner.read_until(my::SP));
  let k = my::atoi::<u32>(scanner.read_until(my::LF));

  let orig = scanner.fold(h, my::LF, Vec::with_capacity(h), | mut v, s | {
    let n: usize = (0..w).fold(0, | x, i | {
      x | if s[i] == b'.' { 0 } else { 1 << i }
    });
    v.push(n);
    v
  });

  let mut ans = 0;
  let mut vec = Vec::with_capacity(h);
  vec.resize(h, 0);

  for row in 0..1 << h {
    for col in 0..1 << w {
      vec.copy_from_slice(&orig);

      each_bit(row, | x: usize | {
        vec[x.trailing_zeros() as usize] = 0
      });

      let cnt = (0..h).fold(0, | x, i | {
        vec[i] &= !col;
        x + vec[i].count_ones()
      });

      if cnt == k {
        ans += 1;
      }
    }
  }

  my_write!(writer, itoa.from(ans), b"\n");
  writer.flush().unwrap();
}

fn main() {
  abc173_c();
}

//------------------------------------------------------------------------
mod my {
  use std::ops::{ Add, Sub, Mul, Div, Rem, Not };
  use num_traits::cast::NumCast;
  use num_traits::identities::{ Zero, One };
  use num_traits::ops::wrapping::WrappingAdd;

  #[allow(dead_code)]
  pub const SP: u8 = b' ';
  #[allow(dead_code)]
  pub const LF: u8 = b'\n';

  macro_rules! num_cast {
    ($v0:expr)                   => { num_traits::cast::cast($v0).unwrap() };
    ($v0:expr, $ret:ty)          => { num_traits::cast::cast::<_, $ret>($v0).unwrap() };
    ($v0:expr, $ret:ty, $arg:ty) => { num_traits::cast::cast::<$arg, $ret>($v0).unwrap() };
  }

  //----------------------------------------------------------------------
  #[allow(dead_code)]
  #[inline(always)]
  pub fn atoi<T>(s: &[u8]) -> T
    where T: Add<Output=T> +
             Sub<Output=T> +
             Mul<Output=T> +
             NumCast +
             Zero
  {
    let n = T::zero();

    if s.is_empty() {
      return n;
    }

    match s[0] {
      b'+' => s[1..].iter().fold(n, | x, b | { (x * num_cast!(10)) + num_cast!(b - b'0') }),
      b'-' => s[1..].iter().fold(n, | x, b | { (x * num_cast!(10)) - num_cast!(b - b'0') }),
      _    => s[0..].iter().fold(n, | x, b | { (x * num_cast!(10)) + num_cast!(b - b'0') }),
    }
  }

  //----------------------------------------------------------------------
  #[derive(Debug)]
  pub struct ItoA {
    buf: Vec<u8>,
  }

  impl ItoA {
    #[allow(dead_code)]
    #[inline(always)]
    pub fn with_capacity(cap: usize) -> Self {
      ItoA {
        buf: Vec::with_capacity(cap),
      }
    }

    #[allow(dead_code)]
    #[inline(always)]
    pub fn from<T>(&mut self, mut n: T) -> &[u8]
      where T: Copy +
               PartialEq +
               PartialOrd +
               Div<Output=T> +
               Rem<Output=T> +
               Not<Output=T> +
               NumCast +
               Zero +
               One +
               WrappingAdd
    {
      let zero = T::zero();
      let one  = T::one();
      let ten  = num_cast!(10);

      self.buf.clear();
      if n == zero {
        self.buf.push(b'0');
        return self.buf.as_slice();
      }

      let mut is_negative = false;
      if n < zero {
        is_negative = true;
        n = (!n).wrapping_add(&one);
      }

      while n > zero {
        self.buf.push(num_cast!(n % ten, u8) + b'0');
        n = n / ten;
      }
      if is_negative {
        self.buf.push(b'-');
      }
      self.buf.reverse();
      self.buf.as_slice()
    }
  } // impl ItoA

  //----------------------------------------------------------------------
  #[derive(Debug)]
  pub struct Scanner<R> {
    reader: R,
    buf   : Vec<u8>,
  }

  impl<R> Scanner<R>
    where R: ::std::io::BufRead
  {
    #[allow(dead_code)]
    #[inline(always)]
    pub fn with_capacity(cap: usize, reader: R) -> Self {
      Scanner {
        reader: reader,
        buf   : Vec::with_capacity(cap),
      }
    }

    #[allow(dead_code)]
    #[inline(always)]
    pub fn read_until(&mut self, delim: u8) -> &[u8] {
      self.buf.clear();
      let mut len = self.reader.read_until(delim, &mut self.buf).unwrap();
      if len == 0 {
        return self.buf.as_slice();
      }

      len -= 1;
      if self.buf[len] == delim {
        self.buf.truncate(len);
      }
      self.buf.as_slice()
    }

    #[allow(dead_code)]
    #[inline(always)]
    pub fn for_each<F>(&mut self, n: usize, delim: u8, mut func: F)
      where F: FnMut(&[u8])
    {
      for _ in 0..n - 1 {
        func(self.read_until(delim));
      }
      func(self.read_until(LF))
    }

    #[allow(dead_code)]
    #[inline(always)]
    pub fn fold<T, F>(&mut self, n: usize, delim: u8, mut init: T, mut func: F) -> T
      where F: FnMut(T, &[u8]) -> T
    {
      for _ in 0..n - 1 {
        init = func(init, self.read_until(delim));
      }
      func(init, self.read_until(LF))
    }
  } // impl<R> Scanner<R>
} // mod my


Measured memory_bytes: 2108