#include<bits/stdc++.h>
using namespace std;
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define ll long long
#define db double
#define el "\n"
#define ld long double
#define rep(i,n) for(int i=0;i<n;i++)
#define rev(i,n) for(int i=n;i>=0;i--)
#define rep_a(i,a,n) for(int i=a;i<n;i++)
#define all(ds) ds.begin(), ds.end()
#define ff first
#define ss second
#define pb push_back
#define mp make_pair
typedef vector< long long > vi;
typedef pair<long long, long long> ii;
typedef priority_queue <ll> pq;
#define o_set tree<ll, null_type,less<ll>, rb_tree_tag,tree_order_statistics_node_update>
const ll mod = 1000000007;
const ll INF = (ll)1e18;
const ll MAXN = 1000006;
ll po(ll x, ll n){
ll ans=1;
while(n>0){ if(n&1) ans=(ans*x)%mod; x=(x*x)%mod; n/=2;}
return ans;
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
// #ifndef ONLINE_JUDGE
// freopen("input.txt", "r" , stdin);
// freopen("output.txt", "w" , stdout);
// #endif
int T=1;
cin >> T;
while(T--){
ll n,x;
cin>>n>>x;
ll a[n+1];
rep(i,n) cin>>a[i+1];
ll ans = 0;
if(x==1){
int l = 0, r = 0;
rep_a(i,1,n+1){
if(a[i]==1) r++;
else{
ans += ((r-l)*(r-l+1))/2;
l=r=i;
}
}
ans += ((r-l)*(r-l+1))/2;
cout<<ans<<el;
continue;
}
vector<ii> pr;
for(ll i=2; i*i<=x; i++){
if(x%i==0){
pr.pb(mp(i,0));
while(x%i==0){
x/=i;
pr.back().ss++;
}
}
}
if(x>1) pr.pb(mp(x,1));
int k = pr.size();
map<vector<int>, int> m;
vector<int> curr(k);
rep(i,k) curr[i]=0;
m[curr]=1;
rep_a(i,1,n+1){
rep(j,k){
while(a[i]%pr[j].ff==0){
a[i]/=pr[j].ff;
curr[j]++;
}
curr[j]-=pr[j].ss;
}
if(a[i]>1){
m.clear();
m[curr]=1;
}
else{
ans+=m[curr];
m[curr]++;
}
}
cout<<ans<<el;
}
cerr << "Time : " << 1000 * ((double)clock()) / (double)CLOCKS_PER_SEC << "ms\n";
return 0;
}