把1-m-1看成是图上的点,如果存在x,使得ax=b(mody),显然b要是gcd(a,m)的倍数,进一步得到gcd(b,m)是gcd(a,m)的倍数,于是我们把1-m-1按照与m的gcd并成一些节点,有倍数关系的连单向边,那么问题就变成了在一个DAG上求最长路,dp一下就可以了,输出方案时用扩展欧几里得解同余方程
#include
#define ll long long
using namespace std;
const int maxn=200000+10;
vector<int> g[maxn];
int dp[maxn],n,m,v[maxn],nxt[maxn];
ll exgcd(ll a,ll b,ll &x,ll &y)
{
ll ret,tmp;
if(!b)
{
x=1;
y=0;
return a;
}
ret=exgcd(b,a%b,x,y);
tmp=x;x=y;y=tmp-a/b*y;
return ret;
}
ll work(ll a,ll b)
{
ll x,y,r1=exgcd(a,m,x,y);
if(b%r1!=0) return -1;
x=((x+m)%m*b/r1)%m;
return x;
}
void dfs(int p)
{
if(dp[p]) return;
int res=0;
for(int i=p*2;iif(g[i].size())
{
dfs(i);
if(dp[i]>res)
{
res=dp[i];
nxt[p]=i;
}
}
dp[p]=res+g[p].size();
}
int main()
{
//freopen("test.in","r",stdin);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
int x;scanf("%d",&x);
v[x]=1;
}
for(int i=1;iif(!v[i])
g[__gcd(i,m)].push_back(i);
dfs(1);
printf("%d\n",dp[1]+(!v[0]));
int u=1,x=1;
while(u)
{
for(int i=0;iint v=g[u][i],ans=work(x,v);
printf("%d\n",ans);
x=v;
}
u=nxt[u];
}
if(!v[0]) puts("0");
return 0;
}