Description

 现有N个数c1,c2,...,cN。对于每个数求有多少个有序二元组(i,j)满足以下式子

                        ci * cj mod P=ck(i,j,k可想等)

其中P为一给定质数。对于每个k对应的答案记为cnt[k],请你将每两个相邻的答案相加,这样答案总个数每次减少1,当答案个数为1时结束(结果对1e9+7取模)。为了感谢wjh、xxb、lmb、cly、ckx、yzj出了一堆简单题,请将他们名字缩写(小写)合并后去重并输出字典序第k大,k为所得结果乘上2333333后取模6666666的结果。

Input

 第一行输入一个组数t(t ≤ 5)。

对于每组数据第一行有两个正整数N,P(1 ≤ N ≤ 100000,2 ≤ P ≤ 100000), P为质数。

第二行N个非负整数c1,c2,...,cN(0 ≤ ci ≤ 1e9)。

Output

 输出共一行,为对应答案的字典序排列(答案为0输出-1)。

 

Sample Input

2 7 3 1 2 3 4 5 6 7 5 7 1 0 2 3 0 

Sample Output

ckybhmwzxjl byjlhwzmckx

HINT

 

例如答案是1 2 3 4 5那么你应该经过以下变化变成一个答案

 

1 2 3 4 5

 

3 5 7 9

 

8 12 16

 

20 28

 

48

题解:

我们令g为质数P的原根,那么对于一个数字ai,唯一存在一个数字bi,使得  。那么我们把所有的ai用这种形式表示,于是对于原本的式子ci*cj≡ck(mod P),有,那么可以有bi+bj=bk。这样问题就从乘法变成了加法,FFT就可以排上用场了。而且你会发现,这里的bi的大小都是在P以内的。这样直接FFT即可,最后特殊处理一下0的情况即可。而对于接下来的一部可以发现最后结果就是C(n-1,0)*a[1]+C(n-1,1)*a[2]+……+C(n-1,n-1)*a[n],可以O(n)求出答案,最后一步是个逆康托展开。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <bitset>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <sstream>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll inff = 0x3f3f3f3f3f3f3f3f;
#define FOR(i,a,b) for(int i(a);i<=(b);++i)
#define FOL(i,a,b) for(int i(a);i>=(b);--i)
#define REW(a,b) memset(a,b,sizeof(a))
#define inf int(0x3f3f3f3f)
#define si(a) scanf("%d",&a)
#define sl(a) scanf("%lld",&a)
#define sd(a) scanf("%lf",&a)
#define ss(a) scanf("%s",a)
#define mod ll(6666666)
#define pb push_back
#define eps 1e-6
#define lc d<<1
#define rc d<<1|1
#define Pll pair<ll,ll>
#define P pair<int,int>
#define pi acos(-1)
ll n,p,g,id[2000008],m,ans[5000008],pr[1000008],prime[1000008],qw[1000008],tot;
ll a[100008],jc[15],inv[100008],mm=1e9+7,vis[15],sss[100008];
char s[15],ss[5008];
inline int read()
{
    int X=0,w=0; char ch=0;
    while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
    while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
void init(int n)
{
    int i,j;
    tot=0;
    prime[1]=1;
    for(i=2;i<=n;i++)
    {
        if(!prime[i]) prime[i]=pr[tot++]=i;
        for(j=0;j<tot&&pr[j]*i<=n;j++)
        {
            prime[i*pr[j]]=pr[j];
            if(i%pr[j]==0) break;
        }
    }
}
ll gmod(ll a,ll b,ll p)
{
    ll res=1;
    while(b)
    {
        if(b&1) res=res*a%p;
        a=a*a%p,b>>=1;
    }
    return res;
}
int root(int x)
{
    int f,phi=x-1;qw[0]=0;
    for(int i=0;phi&&i<tot;i++)
    {
        if(phi%pr[i]==0)
        {
            qw[++qw[0]]=pr[i];
            while(phi%pr[i]==0) phi/=pr[i];
        }
    }
    for(int g=2;g<=x-1;g++)
    {
        f=1;
        for(int i=1;i<=qw[0];i++)
         if(gmod(g,(x-1)/qw[i],x)==1) {f=0;break;}
        if(f) return g;
    }
    return 0;
}
struct CP{
    double x,y;
    CP(){} CP(double a,double b):x(a),y(b){}
    CP operator+(const CP&r) const{return CP(x+r.x,y+r.y);}
    CP operator-(const CP&r) const{return CP(x-r.x,y-r.y);}
    CP operator*(const CP&r) const{return CP(x*r.x-y*r.y,x*r.y+y*r.x);}
}b[5000008],t;
inline void Swap(CP&a,CP&b) {t=a;a=b;b=t;}
inline void fft(CP*a,int f,int n)
{
    int i,j,k;
    for(i=j=0;i<n;i++)
    {
        if(i>j) Swap(a[i],a[j]);
        for(k=n>>1;(j^=k)<k;k>>=1);
    }
    for(int i=1;i<n;i<<=1)
    {
        CP wn(cos(pi/i),f*sin(pi/i));
        for(int j=0;j<n;j+=i<<1)
        {
            CP w(1,0);
            for(int k=0;k<i;k++,w=w*wn)
            {
                CP x=a[j+k],y=w*a[i+j+k];
                a[j+k]=x+y;a[i+j+k]=x-y;
            }
        }
    }
    if(f==-1) FOR(i,0,n) a[i].x/=n;
}
void rkt(ll n,ll k)
{
    ll t,ty=0;
    REW(vis,0);
    n--;
    FOR(i,0,k-1)
    {
        t=n/jc[k-i-1];
        n%=jc[k-i-1];
        for(ll j=0,pos=0;;j++,pos++)
        {
            if(vis[pos]) j--;
            if(j==t){vis[pos]=1;s[ty++]=('a'+pos+1);break;}
        }
    }
}
int main()
{
    cin.tie(0);
    cout.tie(0);
    freopen("date1.in","r",stdin);
    freopen("date1.out","w",stdout);
    int tt;
    cin>>tt;
    ss['b']='b',ss['c']='c',ss['d']='h',ss['e']='j',ss['f']='k',ss['g']='l';
    ss['h']='m',ss['i']='w',ss['j']='x',ss['k']='y',ss['l']='z';
    jc[0]=jc[1]=1;
    for(ll i=2;i<=12;i++) jc[i]=jc[i-1]*i;
    inv[1]=1;
    FOR(i,2,100005)  inv[i]=(mm-mm/i)*inv[mm%i]%mm;
    init(100000);
    while(tt--)
    {
        cin>>n>>p;
        g=root(p);
        ll tmp=1,qw=0,er,sum=1;
        for(int i=1;i<p-1;i++)
        {
            tmp=tmp*g%p;
            id[tmp]=i;
        }
        er=m=p-1;
        for(m=er+m,er=1;er<=m;er<<=1);
        FOR(i,0,er+1) b[i].x=b[i].y=0.0,ans[i]=0;
        FOR(i,1,n)
        {
            a[i]=read();
            if(!(a[i]%p)) qw++;
            else b[id[a[i]%p]].x+=1.0;
        }
        fft(b,1,er);
        FOR(i,0,er) b[i]=b[i]*b[i];
        fft(b,-1,er);
        for(int i=0;i<2*p;i++) ans[i%(p-1)]+=(ll)(b[i].x+0.2);
        for(int i=1;i<=n;i++)
        {
            if(a[i]>=p) er=0;
            else if (a[i]==0) er=2*qw*n-qw*qw;
            else er=ans[id[a[i]]];
            sss[i]=er;
        }
        er=0;
        for(int i=0;i<n;i++)
        {
            er=(er+sum*sss[i+1])%mm;
            sum=(sum*(n-1-i)%mm)*inv[i+1]%mm;
        }
        //cout<<er<<endl;
        er=((er%mod)*2333333)%mod;
        if(er==0) {puts("-1");continue;}
        rkt(er,11);
        for(int i=0;i<11;i++) printf("%c",ss[s[i]]);
        puts("");
    }
    return 0;
}