/*
性质1:逆元的对应性
a*b = 1 => b*a = 1 (mod p) 即模p意义下,a的逆元是b,那么b的逆元也是a
性质2:逆元的随机(均匀)分布性
每个数的逆元都是在[2,p-1]随机散落的
模拟一下符合条件的数出现的情况:
如果某个数x2的逆元是2,那么x2之后的数都不会再满足条件
如果某个数x3的逆元是3,x3<x2,那么x3满足条件,反之x3不满足条件
...
依次类推,当xk=2时,这个算法就停止了,因为再往前不会出现更小的xk'
又因为对称性,xk=2时的逆元就是xk,所以我们大概只要处理sqrt(p)内的逆元,然后翻转一下即可
当然判断条件是xk>inv[xk]时break
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 500005
ll p;
int inv[N];
struct Node{
ll xk,k;
Node(){}
Node(ll xk,ll k):xk(xk),k(k){}
};
vector<Node>v;
map<ll,ll>mp;
void init(){
inv[1] = 1;
int q=sqrt(p);
for(int i = 2; i < min(q+1000ll,p); i++){
inv[i] = (p - p/i) * 1ll * inv[p % i] % p;
if(i==2){
v.push_back(Node(inv[i],i));
mp[i]=inv[i];
mp[inv[i]]=i;
}
else {
Node last=v.back();
if(inv[i]<last.xk){
v.push_back(Node(inv[i],i));
mp[i]=inv[i];
mp[inv[i]]=i;
}
}
if(i>inv[i])return;
}
}
int main(){
int t;cin>>t;
while(t--){
v.clear();
mp.clear();
cin>>p;
if(p==2){
puts("0");continue;
}
init();
cout<<mp.size()<<'\n';
for(auto x:mp)
cout<<x.first<<" "<<x.second<<'\n';
}
}