//This is sky_magpie's last NOIP competition.
//we are born in the dust,and we will fade in the dust.
//I don`t know what sort of destiny is waiting in front of me,what I can only do is keep moving.
//My lord,can I have one more chance?I'm not ready to quit.
//I'm lost in the feeling to be a OIer.
//I don`t ever want to leave.
//I`m eager to be a OIer
//for the rest of my life,
//if only there is one more chance......
//farewell......
#include<bits/stdc++.h>
using namespace std;
long long t,id,n,m,c,f,ans[2],have[1010][1010],start[1000100],cnt,mod=998244353;
vector<long long>len,len1;
char gard[1010][1010];
long long calc(int type)
{
	long long temp=0,hou[1010];
	memset(hou,0,sizeof(hou));
	for(long long i=len.size()-1;i>=0;i--)
	{
		if(!type)
		{
			hou[i]=(hou[i+1]+len[i])%mod;
		}
		else
		{
			hou[i]=(hou[i+1]+len1[i])%mod;
		}
	}
	for(long long i=0;i<len.size();i++)
	{	 
		temp+=(len[i]*hou[i+2])%mod;
	}
	return temp;
}
void find_c()
{
	for(long long i=0;i<cnt;i++)
	{
		len.clear();
		long long flag1=0,flag2=false;
		long long x=(start[i]-1)/m+1,y=(start[i]-1)%m+1;
		for(long long j=x;j<=n;j++)
		{
			if(gard[j][y]=='0')
			{
				len.push_back((have[j][y]-1+mod)%mod);
				if(have[j][y]>1)
				{
					if(flag1&&j-flag1>1)
					{
						flag2=true;
					}
					else if(!flag1)
					{
						flag1=j;
					}
				}
			}
			else
			{
				break;
			}
		}
		if(flag2)
		{
			ans[0]=(calc(0)%mod+ans[0])%mod;
		}
	}
}
void find_f()
{
	int now;
	for(long long i=0;i<cnt;i++)
	{
		len.clear();
		len1.clear();
		long long flag1=0,flag2=0,flag3=0;
		long long x=(start[i]-1)/m+1,y=(start[i]-1)%m+1;
		for(long long j=x;j<=n;j++)
		{
			if(gard[j][y]=='0')
			{
				len.push_back(((have[j][y]-1+mod)%mod));
				len1.push_back(((have[j][y]-1+mod)%mod));
				if(have[j][y]>1)
				{
					if(flag1&&j-flag1>1)
					{
						flag2=j;
					}
					else if(!flag1)
					{
						flag1=j;
					}
				}
			}
			else
			{
				break;
			}
		}		
		if(flag2)            
		{
			for(int i=0;i<len1.size();i++)
			{
				len1[i]=(len1[i]*(len.size()-i-1+mod)%mod)%mod;
				now=len1[i];
			}
			ans[1]=(calc(1)%mod+ans[1])%mod;
		}
	}
}
int main()
{
	freopen("plant.in","r",stdin);
	freopen("plant.out","w",stdout);
	cin>>t>>id;
	while(t--)
	{
		memset(have,0,sizeof(have));
		cnt=ans[0]=ans[1]=0;
		cin>>n>>m>>c>>f;
		for(long long i=1;i<=n;i++)
		{
			for(long long j=1;j<=m;j++)
			{
				cin>>gard[i][j];
			}
		}
		for(long long i=1;i<=n;i++)
		{
			for(long long j=m;j>=1;j--)
			{
				if(gard[i][j]=='0')
				{
					have[i][j]=(have[i][j+1]+1)%mod;
				}	
			}
		}
		for(long long j=1;j<=m;j++)
		{
			for(long long i=1;i<=n;i++)
			{
				if(gard[i][j]=='0'&&(i==1||gard[i-1][j]=='1'))
				{
					start[cnt++]=(i-1)*m+j;
				}
			}
		}
		if(c)
		{
			find_c();
		}
		if(f)
		{
			find_f();
		}
		cout<<ans[0]<<" "<<ans[1]<<endl;
	}
	return 0;
}