/*
hdu 1505 这道题是hdu 1506的加强版,同样时求最大子矩阵面积,但不同之处在于这道题并不是求
直方图的最大矩阵,而是求一个矩形内的最大子矩阵,主要的做法就是把矩形分成若干层,每一层都是
求当前层的最大子矩阵面积,这样就转化成了1505
*/
#include <cstdio>
#include <map>
#include <iostream>
#include<cstring>
#include<bits/stdc++.h>
#define ll long long int
#define M 998244353
using namespace std;
const int inf=0x3f3f3f3f;
int k,m,n;
char mapp[1007][1007];
int h[1007][1007];
int l[1007][1007],r[1007][1007];
int main(){
cin>>k;
while(k--){
cin>>m>>n;
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++){
cin>>mapp[i][j];
}
memset(l,0,sizeof(l));
memset(r,0,sizeof(r));
memset(h,0,sizeof(h));
for(int i=1;i<=m;i++){
l[i][1]=1;
r[i][n]=n;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
if(mapp[j][i]=='F')
h[m-j+1][i]=h[m-j+2][i]+1;
else
h[m-j+1][i]=0;
}
for(int i=1;i<=m;i++)
for(int j=2;j<=n;j++){
int t=j;
while(t>1&&h[i][j]<=h[i][t-1])
t=l[i][t-1];
l[i][j]=t;
}
for(int i=1;i<=m;i++)
for(int j=n-1;j>=1;j--){
int t=j;
while(t<n&&h[i][j]<=h[i][t+1])
t=r[i][t+1];
r[i][j]=t;
}
ll maxx=0;
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++)
if((r[i][j]-l[i][j]+1)*h[i][j]*3>maxx){
maxx=(r[i][j]-l[i][j]+1)*h[i][j]*3;
}
cout<<maxx<<endl;
}
}
/*
hdu 1506 找最大子矩阵面积
不难想到(狗屁)最大子矩阵的面积总是由 一个单位的矩阵 加上 两边更高 的连续矩阵所拼接而成的大矩阵
理解上面一句话。
但是不能直接遍历1~n每一个单位的矩阵去试探左右两边的长度,这样保守估计是一个n平方的算法,所以不妨换一种思考方式
for(ll i=2;i<=n;i++){
ll t=i;
while(t>1&&h[i]<=h[t-1])
t=l[t-1];
l[i]=t;
}
当在搜索下标为i的单位矩阵时,当i-1的下标的单位矩阵高度高于它时,其实我们是已经判断过下标为i-1的单位矩阵的最左端
下标的,所以这就满足dp的条件,只要把左边各个连续且大于h[i]高度的矩阵的最远下边记录下来即可。
*/
#include <cstdio>
#include <map>
#include <iostream>
#include<cstring>
#include<bits/stdc++.h>
#define ll long long int
#define M 998244353
using namespace std;
const int inf=0x3f3f3f3f;
ll n,h[100007];
ll l[100007],r[100007];
int main(){
while(cin>>n){
if(!n)
break;
memset(l,0,sizeof(l));
memset(r,0,sizeof(r));
for(ll i=1;i<=n;i++)
cin>>h[i];
l[1]=1;
r[n]=n;
//初始化 第一个矩阵左边没有比它更高的矩阵,同理最后一个也一样。
for(ll i=2;i<=n;i++){
ll t=i;
while(t>1&&h[i]<=h[t-1])
t=l[t-1];
l[i]=t;
}
for(ll i=n-1;i>=1;i--){
ll t=i;
while(t<n&&h[i]<=h[t+1])
t=r[t+1];
r[i]=t;
}
ll maxn=-1;
for(ll i=1;i<=n;i++){
if((r[i]-l[i]+1)*h[i]>maxn)
maxn=(r[i]-l[i]+1)*h[i];
}
cout<<maxn<<endl;
}
}
/* http://acm.hdu.edu.cn/status.php hdu 1864
对于浮点类型的质量与价值,因为都为小数点后两位,所以都乘100转化为整型进行dp
状态转移方程: dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);
*/
#include <cstdio>
#include <map>
#include <iostream>
#include<cstring>
#include<bits/stdc++.h>
#define ll long long int
#define M 998244353
using namespace std;
const int inf=0x3f3f3f3f;
double q;
int n;
int value[35];
int dp[3000007];
int main(){
while(cin>>q>>n){
if(!n)
break;
int k=1;
memset(dp,0,sizeof(dp));
for(int i=1;i<=n;i++){
int m;
cin>>m;
int a=0,b=0,c=0;
int flag=1;
for(int j=1;j<=m;j++){
char type;
char temp;
double val;
cin>>type>>temp>>val;
if(type=='A'){
a+=(int)(val*100);
}
else if(type=='B'){
b+=(int)(val*100);
}
else if(type=='C'){
c+=(int)(val*100);
}
else{
flag=0; break;
}
}
if(!flag||(a+b+c)>100000||a>60000||b>60000||c>60000)
continue;
value[k++]=a+b+c;
}
for(int i=1;i<k;i++)
for(int j=(int)(q*100);j>=value[i];j--){
dp[j]=max(dp[j],dp[j-value[i]]+value[i]);
}
// cout<<(int)(q*100)<<endl;
double ans=dp[(int)(q*100)]*1.0/100;
printf("%.2lf\n",ans);
}
}
/*
hdu 2955
一道0-1背包的变形,本来看测试数据以为是直接背包概率,结果wa。
然后去看题解,大多数人也犯了这样的错误,错误的原因不同的题解有不同的说法,
我认为 总的被抓概率并不是又各个分概率的和组成的, 这个其实显而易见。
如
1 0.02
2 0.03
被抓的概率显然不是0.5
而是 1-(1-0.02)*(1-0.03)=0.494
所以这样看来背包概率显然不合适,所以有另外一个背包金钱的方法。
dp[j]=max(dp[j],dp[j-money[i]]*(1-chance[i]))
*/
#include <cstdio>
#include <map>
#include <iostream>
#include<cstring>
#include<bits/stdc++.h>
#define ll long long int
#define M 998244353
using namespace std;
const int inf=0x3f3f3f3f;
double dp[10007];
int money[1007];
double chance[1007];
int main(){
int t;
cin>>t;
while(t--){
double p;
int n;
cin>>p>>n;
memset(dp,0,sizeof(dp));
dp[0]=1;
int sum=0;
for(int i=1;i<=n;i++){
cin>>money[i]>>chance[i];
sum+=money[i];
}
for(int i=1;i<=n;i++)
for(int j=sum;j>=money[i];j--){
dp[j]=max(dp[j],dp[j-money[i]]*(1-chance[i]));
}
for(int i=sum;i>=0;i--){
if(dp[i]>=(1-p)){
cout<<i<<endl;
break;
}
}
}
}