#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXN 1000006
#define MAXM 100005
int tree[400006];
int a[100006];
int fact[1000006];
int prime[1000006];
int max(int a, int b)
{
return a > b? a : b;
}
void sieve()
{
fact[1] = 1;fact[0] = 1;
prime[0] = 1;prime[1] = 1;
int i;
for(i=2;i<1000006;i++)
{
if(!prime[i])
{
fact[i] = i;
long long int j = (long long)i*i;
while(j < 1000006)
{
if(!prime[j])
{
prime[j] = 1;
fact[j] = i;
}
j+=i;
}
}
}
}
void build(int node, int l, int r)
{
if(l==r)
{
tree[node] = fact[a[l]];
a[l] /= tree[node];
}
else
{
int mid = (l+r)/2;
build(2*node,l,mid);
build(2*node+1,mid+1,r);
tree[node] = max(tree[2*node],tree[2*node +1]);
}
}
int query(int node, int l, int r, int a, int b)
{
if(tree[node] == 1)
return 1;
if(l>r || l > b || r < a)
return 1;
if(a <= l && r <= b)
return tree[node];
int mid = (l+r)/2;
int left = query(2*node,l,mid,a,b);
int right = query(2*node+1,mid+1,r,a,b);
return max(left,right);
}
void update(int node, int l, int r, int x, int y)
{
if(tree[node] == 1)
return;
if(l > r || l > y || r < x)
return ;
if(l == r)
{
tree[node] = fact[a[l]];
a[l] /= tree[node];
}
else
{
int mid = (l+r)/2;
update(2*node,l,mid,x,y);
update(2*node+1,mid+1,r,x,y);
tree[node] = max(tree[2*node],tree[2*node+1]);
}
}
int main()
{
int t,i;
sieve();
scanf("%d",&t);
while(t--)
{
int n,m;
scanf("%d %d",&n,&m);
memset(a,1,sizeof(a));
memset(tcnt,0,sizeof(tcnt));
memset(tree,1,sizeof(tree));
for(i=0;i<n;i++)
scanf("%d",&a[i]);
build(1,0,n-1);
while(m--)
{
int x,st,end;
scanf("%d %d %d",&x,&st,&end);
st--;end--;
if(x==0)
update(1,0,n-1,st,end);
else
printf("%d ",query(1,0,n-1,st,end));
}
printf("\n");
}
return 0;
}