// 2015暑期多校训练第一场 1,2,3
//
// 本来想一天能够复习一套的,结果实在太艰难,一题差不多都能搞一天呢
// 而且内心的激动也是想在此时分享分享,前两道大神说的水题,我都理解
// 了大半天,第三题更是理解了三四天才懂了那么一丁点.继续加油吧,明天
// 继续搞!
// hdu 5288 OO’s Sequence
//
// 对于一个a[i]记录左边一个L右边一个R,分别
// 代表最接近a[i]并且能够被a[i]整除的位置
// 每个a[i]的贡献值是(R[i] - i) * (i - L[i])
// 用一个pre值,记录每个数出现的位置.
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn = 100008;
const ll MOD = 1e9 + 7;
int a[maxn];
int L[maxn];
int R[maxn];
int n;
vector<int> p[10008];
int pre[maxn];
void init(){
for (int i=1;i<=10000;i++){
p[i].clear();
for (int j=1;j*j<=i;j++){
if (i%j==0){
p[i].push_back(j);
if (j*j!=i)
p[i].push_back(i/j);
}
}
}
}
void input(){
for (int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
}
void solve(){
memset(pre,0,sizeof(pre));
for (int i=1;i<=n;i++){
int u = a[i];
int ind = 0;
for (int j=0;j<p[u].size();j++){
ind = max(ind,pre[p[u][j]]);
}
L[i] = ind;
pre[u] = i;
}
memset(pre,0x7f,sizeof(pre));
for (int i=n;i>=1;i--){
int u = a[i];
int ind = n + 1;
for (int j=0;j<p[u].size();j++){
ind = min(ind,pre[p[u][j]]);
}
R[i] = ind;
pre[u] = i;
}
ll ans = 0;
for (int i=1;i<=n;i++){
ans = (ans + (ll)(i-L[i]) * (R[i] - i))%MOD;
}
printf("%I64d\n",ans);
}
int main(){
init();
freopen("1.txt","r",stdin);
while(scanf("%d",&n)!=EOF){
input();
solve();
}
}
// hdu 5289 Assignment 单调队列
//
// 题目大意:
//
// 题目的意思就是让你求满足最大值最小值之差小与k的区间个数
//
// 解题思路:
//
// 单调队列,众所周知,单调队列能够维护滑动窗口的最大值和最小值
// 的问题.这里两者都有,我们都维护即可.我们用两个指针.一个指针表示
// 当前插入的元素,另一个指针表示满足条件的开始的元素的位置.维护单
// 调队列的时候我们插入一个元素,当发现插入该元素时,不满足题目所要
// 求的条件,并且第一个指针指向的位置出队.这时两个指针之间的距离就
// 是我们所能得到的区间的数目,累加结果就好.最后还要记得当所有的元
// 素都入队时,此时要看看j是否是最后的位置,因为此时还有满足条件的
// 区间.
//
// 感悟:
//
// 这道题多校训练的时候,是MY做出来的,用的就是单调队列,当时并不
// 怎么明白,后来也自己做了一遍,能想到维护最大值和最小值,但是这之间
// 的距离就不太清楚了.看了看题解,发现确实很奇妙.然后自己仔细仔细的
// 体会了一番,确实很不错.感谢这位神牛.也有的大神用的线段树做出来的
// 也有的是RMQ+二分.有多种解法.多开阔开阔思路,总是好的.继续加油哟~~~
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e5 + 8;
int n,k;
int a[maxn];
int deqmax[maxn];
int deqmin[maxn];
void input(){
scanf("%d%d",&n,&k);
for (int i = 1; i <= n; i++){
scanf("%d",&a[i]);
}
}
void solve(){
int headmax,tailmax,headmin,tailmin;
headmax = tailmax = headmin = tailmin = 0;
long long ans = 0;
int j = 1;
for (int i=1;i <= n; i++){
while(headmax < tailmax && a[deqmax[tailmax-1]] <= a[i])
tailmax--;
deqmax[tailmax++] = i;
while(headmin < tailmin && a[deqmin[tailmin-1]] >= a[i])
tailmin--;
deqmin[tailmin++] = i;
while(headmin < tailmin && headmax < tailmax && a[deqmax[headmax]]-a[deqmin[headmin]] >= k){
ans += i - j;
if (j == deqmax[headmax])
headmax++;
if (j == deqmin[headmin])
headmin++;
j++;
}
}
while(j <= n){
ans += n + 1 - j;
j++;
}
printf("%I64d\n",ans);
}
int main(){
int t;
//freopen("1.txt","r",stdin);
scanf("%d",&t);
while(t--){
input();
solve();
}
}
// hdu 5290 Bombing plan
//
// 题目大意:
//
// 给你一颗树,树上每个节点有一个权值w,当炸毁一个节点
// 时,距离它为w以内的点都被炸毁.则问当所有点被炸毁时
// 最小需要炸毁几个点.
//
// 解题思路:
//
// 树形dp.我们设立两个数组F[I][J],G[I][J].前者表示
// I及I子树中所有节点全被炸毁,并且沿父节点向上距离
// 为J的点也被炸毁.后者表示I及I的子树中部分节点被炸毁
// 并且未被炸毁的点离I最远为J.
// 转移方程为:
// 不取i点
// F[i][j] = F[v][j+1] + min(F[L][0...j+1],G[L][0...j-1]);
// G[i][j] = g[v][j-1] + min(F[L][0....j],G[L][0...j-1]);
// G[i][0] = sigma(f[v][0]);
//
// 取i点
// F[i][w[i]] = 1 + min(F[L][0...w[u]+1],G[L][0...w[u]-1]);
//
// 如果不好理解的话,那么本人按照自己的理解说一下,首先是F[i][j].
// 先选一个满足条件的能达到i向上距离为j的则为F[v][j+1].此时其他
// 的节点,子节点子树全被炸毁的范围F[L][0...j+1],子节点子树未被
// 全部炸毁g[i][j-1].G[i][j]同样是首先选择一个离i未炸毁的G[v][j-1]
// 其他的还是两种选择,要么未炸毁距离小于等于j要么全被炸毁.
//
// 初始化的时候单个叶子节点g[i][0] = 0,f[i][w[i]] = 1;其他的无穷大
// 但是不宜太大,容易造成数据溢出
//
// 看到一位大神写的在这题中,将无根树转化为有根树的时候,将1作为根.
// 并将1本身的节点另起一个编号挂在1上.这样的做法我感觉十分奇妙.自己还是
// 不很理解.希望大牛们能够不吝惜的指点小子一二.小子不慎感激
//
// 感悟:
//
// 多校第一场的第三题,当时根本就不会做,题解也看不懂.现在经过了玩耍的开心
// 时间,是时候逼迫自己去理解了,要不然水平怎么能提高呢,继续加油吧
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#define cls(x,a) memset(x,(a),sizeof(x))
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int maxn = 1e5 + 8;
const int inf = 0x01010101;
vector<int> e[maxn];
int a[maxn];
int F[maxn][111];
int G[maxn][111];
int p[maxn][111];
int q[maxn][111];
int n;
void input(){
for (int i=1;i<=n;i++){
e[i].clear();
}
for (int i = 1;i <= n;i++){
scanf("%d",&a[i]);
}
e[1].push_back(n+1);
for (int i=1;i < n;i++){
int u,v;
scanf("%d%d",&u,&v);
e[u].push_back(v);
e[v].push_back(u);
}
cls(F,inf);
cls(G,inf);
cls(p,inf);
cls(q,inf);
}
void dfs(int u,int fa){
for (int i=0;i<e[u].size();i++){
int v = e[u][i];
if (v == fa)
continue;
dfs(v,u);
}
if (e[u].size()==1){
G[u][0] = 0;
F[u][a[u]] = 1;
return;
}
for (int i=0;i<e[u].size();i++){
int v = e[u][i];
if (v == fa)
continue;
p[v][0] = F[v][0];
q[v][0] = G[v][0];
for (int j=1;j<103;j++){
p[v][j] = min(p[v][j-1],F[v][j]);
q[v][j] = min(q[v][j-1],G[v][j]);
}
}
for (int j=0;j<103;j++){
for (int k=0;k<e[u].size();k++){
int v = e[u][k];
if (v == fa)
continue;
if (F[v][j+1] == inf)
continue;
int f = F[v][j+1];
for (int i=0;i<e[u].size();i++){
int t = e[u][i];
if (i==k || t == fa)
continue;
if (j)
f += min(p[t][j+1],q[t][j-1]);
else
f += p[t][j+1];
}
F[u][j] = min(F[u][j],f);
}
}
int g = 0;
for (int i=0;i<e[u].size();i++){
int v = e[u][i];
if (v==fa)
continue;
g += F[v][0];
}
G[u][0] = min(G[u][0],g);
for (int j=1;j<103;j++){
for (int k=0;k<e[u].size();k++){
int v = e[u][k];
if (v == fa)
continue;
if (G[v][j-1] == inf)
continue;
g = G[v][j-1];
for (int i=0;i<e[u].size();i++){
int t = e[u][i];
if (i==k || t == fa)
continue;
g += min(p[t][j],q[t][j-1]);
}
G[u][j] = min(G[u][j],g);
}
}
int f = 1;
for (int i=0;i<e[u].size();i++){
int v = e[u][i];
if (v == fa)
continue;
if (a[u]){
f += min(p[v][a[u]+1],q[v][a[u]-1]);
}else {
f += p[v][a[u]+1];
}
}
F[u][a[u]] = min(F[u][a[u]],f);
}
void solve(){
dfs(1,0);
int ans = inf;
for (int j=0;j<103;j++){
ans = min(ans,F[1][j]);
}
printf("%d\n",ans);
}
int main(){
freopen("1.txt","r",stdin);
while(scanf("%d",&n)!=EOF){
input();
solve();
}
}