#include
#include
#include
#include
#define ll long long
#define pll pair
using namespace std;
ll fac[70][2],eqans[70][5],tempa[70],m[70],ans[1000100],n,a,cnt,w;
void frac(ll n)//分解模
{
for(int i=2;i*i<=n;++i)
if(n%i==0)
{
while(n%i==0)
{
fac[cnt][0]=i;
++fac[cnt][1];
n/=i;
}
++cnt;
}
if(n>1)
{
fac[cnt][0]=n;
++fac[cnt++][1];
}
}
void exgcd(ll a,ll b,ll &d,ll &x,ll &y)
{
if(!b){x=1;d=a;y=0;}
else
{
exgcd(b,a%b,d,y,x);
y-=a/b*x;
}
}
ll mul(ll a,ll b,ll p)
{
ll res=0;
while(b)
{
if(b&1)res=(res+a)%p;
a=(a+a)%p;
b>>=1;
}
return res;
}
ll pow(ll a,ll b,ll p)
{
ll res=1%p;
while(b)
{
if(b&1)res=mul(res,a,p);
a=mul(a,a,p);
b>>=1;
}
return res;
}
pll mul(pll a,pll b,ll p)//二次域上乘法
{
pll res;
res.first=(a.first*b.first%p+a.second*b.second%p*w%p)%p;
res.second=(a.first*b.second%p+a.second*b.first%p)%p;
return res;
}
pll pow(pll a,ll b,ll p)//二次域上快速幂
{
pll res=pll(1,0);
while(b)
{
if(b&1)res=mul(res,a,p);
a=mul(a,a,p);
b>>=1;
}
return res;
}
ll work(ll a,ll p)//解二次同余方程模奇质数
{
if(a==0)return 0;
if(pow(a,(p-1)/2,p)==p-1)return -1;
ll t;
while(1)
{
t=rand()%p;
w=((t*t-a)%p+p)%p;
if(pow(w,(p-1)/2,p)==p-1)break;
}
pll tmp=pll(t,1);
return pow(tmp,(p+1)/2,p).first;
}
ll work2(ll a)//枚举二次同余方程模8同余的解
{
for(int i=0;i<8;++i)
if(i*i%8==a%8)
return i;
return -1;
}
ll solve(ll a,ll p,ll k)//求二次同余方程模质数的幂的一个解
{
ll prep=1,nowp=p,w;
if(p==2)//质数为2的时候,a=0则0是一个解,a=1则1是一个解,a=2 or a=3无解
{
if(a==0)return 0;
if(a==1)return 1;
if(a==2||a==3)return -1;
w=work2(a);prep=2;nowp=8;k-=2;//此时只用讨论模8(模4的已经讨论完了)
}
else w=work(a%p,p);
if(w==-1)return -1;
for(int i=1;i*=p;
nowp*=p;
ll d,x,y,c;
c=((a-w*w)%nowp+nowp)%nowp;
exgcd(2*w*prep,nowp,d,x,y);
if(c%d==0)w=(w+(c/d*x%nowp+nowp)%(nowp/d)*prep)%nowp;
else return -1;
}
return w;
}
ll CRT()//合并方程组
{
ll res=0;
for(int i=0;ix,y,d,Mi=n/m[i];
exgcd(Mi,m[i],d,x,y);
res=(res+Mi*x*tempa[i])%n;
}
if(res<0)res+=n;
return res;
}
void dfs(int pos)//决定选取哪些方程做CRT
{
if(pos==cnt)
{
ans[++ans[0]]=CRT();
return;
}
m[pos]=pow(fac[pos][0],fac[pos][1],n+1);
for(int i=0;ipos][19];++i)
{
tempa[pos]=eqans[pos][i];
dfs(pos+1);
}
}
void quadratic_congruence()//二次同余主函数
{
for(int i=0;i0],fac[i][1],n+1),t=solve(a%p,fac[i][0],fac[i][1]);
if(t==-1)//如果有一个无解就返回
{
puts("No Solution");
return;
}
sets;
set::iterator iter;
if(t==0)//以前的程序有bug,如果整除的话那么不只有2或4个解
{
ll pp=pow(fac[i][0],(fac[i][1]+1)/2,n+1);
for(int i=0;pp*is.insert(pp*i);
}
else
{
s.insert(t);
s.insert(p-t);
if(fac[i][0]==2&&fac[i][1]>1)s.insert((t+p/2)%p);
if(fac[i][0]==2&&fac[i][1]>1)s.insert(((p/2-t)+p)%p);
}
for(iter=s.begin();iter!=s.end();iter++)
eqans[i][eqans[i][19]++]=*iter;
}
dfs(0);
}
int main()
{
scanf("%I64d%I64d",&a,&n);
frac(n);
quadratic_congruence();
sort(ans+1,ans+ans[0]+1);
for(int i=1;i<=ans[0];++i)
printf("%I64d%c",ans[i],i==ans[0]?'
':' ');
}