/*
* @author Santosh Kumar Shaw (devsks)
* @quote "Code like there's no tommorow!"
*/
#include "bits/stdc++.h"
#include <unordered_map>
#define FOR(X,Y) for(ll X = 0; X < Y; X++)
#define ll long long
#define newTrie (myTrie*) calloc(1, sizeof(myTrie))
#define pb push_back
using namespace std;
struct myTrie{
bool isWord;
struct myTrie *next[26];
int fq[26];
int srtInd[26];
ll len[26];
};
ll mod, isfill[26],reg;
string mystr;
char prnstr[200002], ansStr[200002];
void insertTrie(myTrie *root, int start)
{
for(int i = start; i < mystr.length(); ++i)
{
int index = mystr[i]-'a';
root->fq[index]+=1;
ll valwa = (mystr.length() - i);
root->len[index] += ( (valwa*(valwa+1)>>1) + valwa*(i-start));
if(root->fq[index]==1)
{
root->srtInd[index] = i;
break;
}
else
{
if(root->fq[index]==2 && (root->next[index] == NULL) )
{
root->next[index] = newTrie;
myTrie* child = root->next[index];
if(root->srtInd[index]+1 >= mystr.length())
child->isWord = true;
else
{
int newInd = root->srtInd[index]+1;
char ch = mystr[newInd];
child->fq[ch-'a'] +=1;
child->srtInd[ch-'a'] = newInd;
valwa = (mystr.length() - newInd);
child->len[ch-'a'] += ( (valwa*(valwa+1)>>1) + valwa*( i+1 - start));
}
}
root = root->next[index];
}
}
root->isWord = true;
}
char printTrie(myTrie *root, ll level)
{
for( int i = 0; i < 26; i++)
{
if(root->fq[i] == 1 && root->len[i] >= reg )
{
ll low = 1, high = (mystr.length() - root->srtInd[i]), mid, ind = -1;
while(low<=high)
{
mid = low+high>>1;
ll cal = mid*(mid+1)>>1;
cal += (mid*(level));
if(cal >= reg)
{
ind = mid;
high = mid-1;
}
else
low = mid+1;
}
if(ind > 1)
{
reg -= ( (ind*(ind-1)>>1) + (ind-1)*level);
}
if( (reg-1) < level)
{
return prnstr[reg-1];
}
else
{
reg-=level;
if(root->srtInd[i] +reg-1> mystr.length())
return 'z';
//cout<<reg<<" ";
return mystr[root->srtInd[i] +reg-1];
}
/*if (root->next[i] == NULL)
{
root->next[i] = newTrie;
myTrie* child = root->next[i];
if(root->srtInd[i]+1 == mystr.length())
child->isWord = true;
else
{
int newInd = root->srtInd[i]+1;
char ch = mystr[newInd];
child->fq[ch-'a'] +=1;
child->srtInd[ch-'a'] = newInd;
ll valwa = (mystr.length() - newInd);
child->len[ch-'a'] += ( (valwa*(valwa+1)>>1) + valwa*(level+1));
}
}*/
// cout<<root->srtInd[i]<<" "<<mystr[root->srtInd[i]]<<" "<<root->len[i]<<"\n";
}
else if (root->next[i] && root->len[i] >= reg)
{
prnstr[level] = i + 'a';
ll lenwa = root->fq[i] * (level + 1);
if(reg > lenwa)
{
reg-=lenwa;
return printTrie(root->next[i], level + 1);
}
else
return prnstr[ (reg-1)%(level+1)];
}
else
reg-=root->len[i];
}
return 'z';
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
// cin>>mystr;
mystr="";
for(int i=0;i<200000;i++){
if(i%2)
mystr.pb('a');
else
mystr.pb('b');
}
// string is of size 10^4
vector< myTrie* > myarr(26,nullptr);
vector< vector<int> > myarrInd(26);
ll charSum[26] = {0};
FOR(i,mystr.length())
{
int lkw = mystr.length() - i;
myarrInd[mystr[i]-'a'].push_back(i);
// if(myarr[mystr[i]-'a']==nullptr)
// myarr[mystr[i]-'a'] = newTrie;
// insertTrie(myarr[mystr[i]-'a'], i);
charSum[mystr[i]-'a'] += (lkw*(lkw+1)>>1);
}
/*
FOR(i,26)
{
if(myarr[i]!=nullptr)
{
for(int q = 1; q <= charSum[i];++q)
{
reg = q;
char ansch = printTrie(myarr[i],0);
cout<<ansch;
}
cout<<"\n";
}
//break;
}
return 0;*/
for(register int i = 1; i < 26; ++i)
charSum[i] += charSum[i - 1];
ll q,myp, myg = 0;
cin>>q;
FOR(qq, q)
{
cin>>myp>>mod;
reg = (myp*myg)%mod+1;
int ind = -1, low = 0, high = 25, mid;
while(low <= high)
{
mid = low+high>>1;
if(charSum[mid] >= reg)
{
ind = mid;
high= mid-1;
}
else
low = mid+1;
}
if(!isfill[ind])
{
if(myarr[ind]==nullptr)
myarr[ind] = newTrie;
for(auto it = myarrInd[ind].begin(); it!= myarrInd[ind].end(); ++it )
insertTrie(myarr[ind], *it);
isfill[ind]=1;
}
if(ind > 0)
reg -= charSum[ind-1];
char ch = printTrie(myarr[ind], 0LL);
myg += ch;
ansStr[qq] = ch;
}
FOR(qq,q)
cout<<ansStr[qq]<<"\n";
return 0;
}