競プロをしながら、節約と株式投資でセミリタイアを目指す東大卒のブログ

東大卒でメーカー勤務の私がセミリタイアするために投資や競プロを頑張っていこうという趣旨で始めたブログです。独身男性です。火木土日に更新予定です。お金について考えています。

競技プログラミング~HHKBで書いたコード~

using System;
using System.Numerics;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace debug
{
    class main
    {
        static void Main(string args)
        {
            //問題クラスを展開
            ProgramE a = new ProgramE();
            a.main();//実行する

        }

    }
    //HHKB
    class ProgramA
    {
        public void main()
        {
            //入力
            string t = Console.ReadLine();
            string s = Console.ReadLine();
            //Yなら大文字(32を引く)出力、Nなら普通に出す
            if (t[0] == 'Y')
                Console.WriteLine((char)(s[0] - 32));
            else
                Console.WriteLine(s);

        }
    }

    class ProgramB
    {
        public void main()
        {
            //入力
            string s = Console.ReadLine().Split(' ');
            int h = int.Parse(s[0]);
            int w = int.Parse(s[1]);

            int[,] huton = new int[hw];
            int ans = 0;

            //配列作成
            for (int i = 0i < hi++)
            {
                string t = Console.ReadLine();
                for (int j = 0j < wj++)
                {
                    if (t[j] == '.')
                        huton[ij] = 0;
                    else
                        huton[ij] = 1;
                }
            }


            //すべてのマスで検索、ただし、w-1のときはヨコ判定はなく、h-1のときはタテ判定はない
            for(int i = 0;i < h;i++)
                for (int j = 0j < wj++)
                {
                    if (j != w - 1)
                        if (huton[ij] == 0 && huton[ij + 1] == 0)
                            ans++;
                    if (i != h - 1)
                        if (huton[ij] == 0 && huton[i + 1j] == 0)
                            ans++;
                }

            //答え出力
            Console.WriteLine(ans);



        }
    }

    class ProgramC
    {
        public void main()
        {

            //入力
            int n = int.Parse(Console.ReadLine());


            string a = Console.ReadLine().Split(' ');
            int count  = new int[200002];//答としては200001まである
            int index = 0;//最小としての答は残しておく

            for (int i = 0i < ni++)
            {
                count[int.Parse(a[i])] = 1;//どの数があったかリストにしておく
                for (int j = indexj < 200002j++)//一意的なので逆に調べないようにする。現在の最小から0のところを探せばよい
                {
                    if (count[j] == 0)//もし、数えて0ならそれが現在の最小
                    {
                        Console.WriteLine(j);
                        index = j;//更新
                        break;//次のループへ
                    }
                }
            }

        }

    }


    class ProgramE
    {
        public void main()
        {
            //入力
            string s = Console.ReadLine().Split(' ');
            int h = int.Parse(s[0]);
            int w = int.Parse(s[1]);
            long mod = 1000000000 + 7;

            long[,] huton = new long[hw];
            long[,] num_w = new long[hw];
            long[,] num_h = new long[hw];
            long count = 0;

            //迷路作成と横で影響のある電球の数を見ておく
            for (int i = 0i < hi++)
            {

                long temp = 0;
                string t = Console.ReadLine();
                for (int j = 0j < wj++)
                {
                    if (t[j] == '.')
                    {
                        huton[ij] = 0;
                        count++;
                        temp++;
                    }
                    else
                    {
                        huton[ij] = 1;
                        num_w[ij - temp] = temp;
                        temp = 0;
                    }

                    if (j == w - 1 && temp > 0)
                    {
                        num_w[ij - temp + 1] = temp;
                    }
                }
            }

            //タテで電球の数の影響があるのを見ておく
            for (int i = 0i < wi++)
            {
                long temp = 0;
                for (int j = 0j < hj++)
                {

                    if (huton[ji] == 0)
                        temp++;
                    else
                    {
                        num_h[j - tempi] = temp;
                        temp = 0;
                    }

                    if(j == h - 1 && temp > 0)
                    {
                        num_h[j - temp + 1i] = temp;
                    }
                }
            }

            //2のn乗はあらかじめメモ化しておく
            long two_list = new long[count + 1];
            two_list[0] = 1;

            for (int i = 1i <= counti++)
                two_list[i] = 2 * two_list[i - 1] % mod;


            //それぞれの位置で数を足す
            long ans = 0;
            for (int i = 0i < wi++)
            {
                for (int j = 0j < hj++)
                {

                    if (huton[ji] == 0)
                    {
                        long tento = count - (num_w[ji] + num_h[ji] - 1);
                        if (j < h - 1)
                            num_h[j + 1i] = num_h[ji];//累積和
                        if (i < w - 1)
                            num_w[ji + 1] = num_w[ji];//累積和
                        ans += (two_list[count] - two_list[tento] + mod) % mod;//その場所が照らされる通り数を見る
                        ans %= mod;
                    }
                }


            }

            //答え出力
            Console.WriteLine(ans);

        }


    }

}