Problem:
Score : 700 points

Problem Statement

There are some coins in the xy-plane.
The positions of the coins are represented by a grid of characters with H rows and W columns.
If the character at the i-th row and j-th column, s_{ij}, is #, there is one coin at point (i,j); if that character is ., there is no coin at point (i,j). There are no other coins in the xy-plane.

There is no coin at point (x,y) where 1\leq i\leq H,1\leq j\leq W does not hold.
There is also no coin at point (x,y) where x or y (or both) is not an integer.
Additionally, two or more coins never exist at the same point.

Find the number of triples of different coins that satisfy the following condition:

Choosing any two of the three coins would result in the same Manhattan distance between the points where they exist.

Here, the Manhattan distance between points (x,y) and (x',y') is |x-x'|+|y-y'|.
Two triples are considered the same if the only difference between them is the order of the coins.

Constraints

1 \leq H,W \leq 300

s_{ij} is # or ..

Input

Input is given from Standard Input in the following format:

H W
s_{11}...s_{1W}
:
s_{H1}...s_{HW}

Output

Print the number of triples that satisfy the condition.

Sample Input 1

5 4
#.##
.##.
#...
..##
...#

Sample Output 1

3

((1,1),(1,3),(2,2)),((1,1),(2,2),(3,1)) and ((1,3),(3,1),(4,4)) satisfy the condition.

Sample Input 2

13 27
......#.........#.......#..
#############...#.....###..
..............#####...##...
...#######......#...#######
...#.....#.....###...#...#.
...#######....#.#.#.#.###.#
..............#.#.#...#.#..
#############.#.#.#...###..
#...........#...#...#######
#..#######..#...#...#.....#
#..#.....#..#...#...#.###.#
#..#######..#...#...#.#.#.#
#..........##...#...#.#####

Sample Output 2

870

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <cmath>
#include <map>
#include <queue>
#include <iomanip>
#include <set>
#include <tuple>
#define mkp make_pair
#define mkt make_tuple
#define rep(i,n) for(int i = 0; i < (n); ++i)
using namespace std;
typedef long long ll;
const ll MOD=1e9+7;
template<class T> void chmin(T &a,const T &b){if(a>b) a=b;}
template<class T> void chmax(T &a,const T &b){if(a<b) a=b;}

int H,W;

const int L=350;
int board[1001][1001];
const int X=990;
int rig[2002][1002];
int lef[2002][1002];

void init(){
    for(int i=X-1;i>=0;i--){
        for(int j=0;i+j<X;j++){
            rig[X-i][j+1]+=rig[X-i][j];
            rig[X-i][j+1]+=board[i+j][j];
        }
    }
    for(int i=1;i<X;i++){
        for(int j=0;i+j<X;j++){
            rig[X+i][j+1]+=rig[X+i][j];
            rig[X+i][j+1]+=board[j][i+j];
        }
    }

    for(int i=0;i<X;i++){
        for(int j=0;i-j>=0;j++){
            lef[i][j+1]+=lef[i][j];
            lef[i][j+1]+=board[j][i-j];
        }
    }
    for(int i=1;i<X;i++){
        for(int j=0;i+j<X;j++){
            lef[X-1+i][j+1]+=lef[X-1+i][j];
            lef[X-1+i][j+1]+=board[i+j][X-1-j];
        }
    }
}

int leftquery(int ax,int ay,int bx,int by){
    if(ax>bx){
        swap(ax,bx);
        swap(ay,by);
    }
    int p=ax+ay;
    int px=0;
    if(p>X-1) px=p-(X-1);
    int py=p;
    if(p>X-1) py=X-1;
    int zero=px-py;
    int s=((ax-ay)-zero)/2;
    int t=((bx-by)-zero)/2;
    return lef[p][t+1]-lef[p][s];
}

int rightquery(int ax,int ay,int bx,int by){
    //cout<<ax<<" "<<ay<<" "<<bx<<" "<<by<<endl;
    if(ax>bx){
        swap(ax,bx);
        swap(ay,by);
    }
    int p=ay-ax+X;
    int px=0;
    if(ay-ax<0) px=ax-ay;
    int py=0;
    if(ay-ax>0) py=ay-ax;
    int zero=px+py;
    int s=((ax+ay)-zero)/2;
    int t=((bx+by)-zero)/2;
    return rig[p][t+1]-rig[p][s];
}

int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0};

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

  cin>>H>>W;
  vector<string> S(H);
  rep(i,H) cin>>S[i];

  for(int i=0;i<H;i++) for(int j=0;j<W;j++){
      if(S[i][j]=='#') board[L+i][L+j]=1;
  }

  init();

  ll ans=0;
  for(int len=1;len<=300;len++){
      for(int k=0;k<4;k++){
          for(int i=0;i<H;i++) for(int j=0;j<W;j++){
              int x=L+i;int y=L+j;
              int ax=x+dx[k]*len;
              int ay=y+dy[k]*len;
              int bx=x+dx[(k+1)%4]*len;
              int by=y+dy[(k+1)%4]*len;
              if(board[ax][ay]==1&&board[bx][by]==1){
                  int res=0;
                  if(k%2==0) res+=leftquery(x+x-ax,y+y-ay,x+x-bx,y+y-by);
                  else res+=rightquery(x+x-ax,y+y-ay,x+x-bx,y+y-by);
                  ans+=res;
                  //cout<<i<<" "<<j<<" "<<k<<" "<<len<<" "<<res<<endl;
                  //if(i==3&&j==3) exit(0);
              }
          }
      }

      for(int k=0;k<4;k++){
          for(int i=0;i<H;i++) for(int j=0;j<W;j++){
              int x=L+i;int y=L+j;
              int ax=x+dx[k]*len;
              int ay=y+dy[k]*len;
              int bx=x+dx[(k+1)%4]*len;
              int by=y+dy[(k+1)%4]*len;
              int cx=x+dx[(k+2)%4]*len;
              int cy=y+dy[(k+2)%4]*len;
              if(board[ax][ay]&&board[bx][by]&&board[cx][cy]) ans--;
          }
      }
  }

  cout<<ans<<endl;

  return 0;
}