[数论 DAG最长路] Codeforces 772C VK Cup 2017

来源:互联网 发布:淘宝展现关键词是什么 编辑:程序博客网 时间:2024/04/28 14:56

axb(modm) 有解就是 (a,m)|b 也就是 (a,m)|(b,m)
那么把数按照和m的gcd的整除关系 建成DAG 跑一个最长链

#include<cstdio>#include<cstdlib>#include<algorithm>#include<vector>#define pb push_back using namespace std;typedef long long ll;const int N=200005;int n,m;int a[N],vst[N];vector<int> b[N];int f[N],g[N],pre[N];#define read(x) scanf("%d",&(x))int pnt,ans[N];typedef pair<int,int> abcd;pair<int,int> Gcd(int a,int b){  if (!b) return abcd(1,0);  abcd t=Gcd(b,a%b);  return abcd(t.second,t.first-a/b*t.second);}inline int solve(ll a,ll b){  abcd t=Gcd(a,m); int d=t.first*a+t.second*m;  return ((b/d)*(t.first%m+m)%m)%m;}int main(){  freopen("t.in","r",stdin);  freopen("t.out","w",stdout);  read(n); read(m);  for (int i=1;i<=n;i++) read(a[i]),vst[a[i]]=1;  for (int i=0,d;i<m;i++)    if (!vst[i])      d=__gcd(i,m),g[d%m]++,f[d%m]++,b[d%m].pb(i);  for (int j=0;j<m;j++) pre[j]=-1;  for (int i=1;i<m;i++)    for (int j=i+i;j<=m;j+=i)      if (f[j%m]<g[j%m]+f[i])    f[j%m]=max(f[j%m],g[j%m]+f[i]),pre[j%m]=i;  int k=0;  for (int j=0;j<m;j++) if (!vst[j] && f[j]>f[k]) k=j;  while (k!=-1){    for (int x:b[k]) ans[++pnt]=x;    k=pre[k];  }  reverse(ans+1,ans+pnt+1);  for (int i=pnt;i>1;i--)    ans[i]=solve(ans[i-1],ans[i]);  printf("%d\n",pnt);  for (int i=1;i<=pnt;i++)    printf("%d ",ans[i]);  return 0;}