Team Ai
Datasetpublic

hschumann2/TempleOS-Source-Code

sourceHugging Faceupdated 1y agoView on Hugging Face
0likes847downloads
MagicPairs.txt377 linesDownload Raw Back to Demo
1 2/*The magic pairs problem:3 4Let SumFact(n) be the sum of factors5of n.6 7Find all n1,n2 in a range such that8 9SumFact(n1)-n1-1==n2  and10SumFact(n2)-n2-1==n111 12-----------------------------------------------------13To find SumFact(k), start with prime factorization:14 15k=(p1^n1)(p2^n2) ... (pN^nN)16 17THEN,18 19SumFact(k)=(1+p1+p1^2...p1^n1)*(1+p2+p2^2...p2^n2)*20(1+pN+pN^2...pN^nN)21 22PROOF:23 24Do a couple examples -- it's obvious:25 2648=2^4*327 28SumFact(48)=(1+2+4+8+16)*(1+3)=1+2+4+8+16+3+6+12+24+4829 3075=3*5^231 32SumFact(75)=(1+3)*(1+5+25)    =1+5+25+3+15+7533 34Corollary:35 36SumFact(k)=SumFact(p1^n1)*SumFact(p2^n2)*...*SumFact(pN^nN)37 38*/39 40//Primes are needed to sqrt(N).  Therefore, we can use U32.41class PowPrime42{43  I64 n;44  I64 sumfact; //Sumfacts for powers of primes are needed beyond sqrt(N)45};46 47class Prime48{49  U32 prime,pow_cnt;50  PowPrime *pp;51};52 53I64 *PrimesNew(I64 N,I64 *_sqrt_primes,I64 *_cbrt_primes)54{55  I64 i,j,sqrt=Ceil(Sqrt(N)),cbrt=Ceil(N`(1/3.0)),sqrt_sqrt=Ceil(Sqrt(sqrt)),56        sqrt_primes=0,cbrt_primes=0;57  U8 *s=CAlloc((sqrt+1+7)/8);58  Prime *primes,*p;59 60  for (i=2;i<=sqrt_sqrt;i++) {61    if (!Bt(s,i)) {62      j=i*2;63      while (j<=sqrt) {64        Bts(s,j);65        j+=i;66      }67    }68  }69  for (i=2;i<=sqrt;i++)70    if (!Bt(s,i)) {71      sqrt_primes++; //Count primes72      if (i<=cbrt)73        cbrt_primes++;74    }75 76  p=primes=CAlloc(sqrt_primes*sizeof(Prime));77  for (i=2;i<=sqrt;i++)78    if (!Bt(s,i)) {79      p->prime=i;80      p++;81    }82  Free(s);83 84  *_sqrt_primes=sqrt_primes;85  *_cbrt_primes=cbrt_primes;86  return primes;87}88 89PowPrime *PowPrimesNew(I64 N,I64 sqrt_primes,Prime *primes,I64 *_num_powprimes)90{91  I64 i,j,k,sf,num_powprimes=0;92  Prime *p;93  PowPrime *powprimes,*pp;94 95  p=primes;96  for (i=0;i<sqrt_primes;i++) {97    num_powprimes+=Floor(Ln(N)/Ln(p->prime));98    p++;99  }100 101  p=primes;102  pp=powprimes=MAlloc(num_powprimes*sizeof(PowPrime));103  for (i=0;i<sqrt_primes;i++) {104    p->pp=pp;105    j=p->prime;106    k=1;107    sf=1;108    while (j<N) {109      sf+=j;110      pp->n=j;111      pp->sumfact=sf;112      j*=p->prime;113      pp++;114      p->pow_cnt++;115    }116    p++;117  }118  *_num_powprimes=num_powprimes;119  return powprimes;120}121 122I64 SumFact(I64 n,I64 sqrt_primes,Prime *p)123{124  I64 i,k,sf=1;125  PowPrime *pp;126  if (n<2)127    return 1;128  for (i=0;i<sqrt_primes;i++) {129    k=0;130    while (!(n%p->prime)) {131      n/=p->prime;132      k++;133    }134    if (k) {135      pp=p->pp+(k-1);136      sf*=pp->sumfact;137      if (n==1)138        return sf;139    }140    p++;141  }142  return sf*(1+n); //Prime143}144 145Bool TestSumFact(I64 n,I64 target_sf,I64 sqrt_primes,I64 cbrt_primes,Prime *p)146{147  I64 i=0,k,b,x1,x2;148  PowPrime *pp;149  F64 disc;150  if (n<2)151    return FALSE;152  while (i++<cbrt_primes) {153    k=0;154    while (!(n%p->prime)) {155      n/=p->prime;156      k++;157    }158    if (k) {159      pp=p->pp+(k-1);160      if (ModU64(&target_sf,pp->sumfact))161        return FALSE;162      if (n==1) {163        if (target_sf==1)164          return TRUE;165        else166          return FALSE;167      }168    }169    p++;170  }171/*  At this point we have three possible cases to test1721)n==p1         ->sf==(1+p1)        ?1732)n==p1*p1      ->sf==(1+p1+p1^2)   ?1743)n==p1*p2      ->sf==(p1+1)*(p2+1) ?175 176*/177  if (1+n==target_sf) {178    while (i++<sqrt_primes) {179      k=0;180      while (!(n%p->prime)) {181        n/=p->prime;182        k++;183      }184      if (k) {185        pp=p->pp+(k-1);186        if (ModU64(&target_sf,pp->sumfact))187          return FALSE;188        if (n==1) {189          if (target_sf==1)190            return TRUE;191          else192            return FALSE;193        }194      }195      p++;196    }197    if (1+n==target_sf)198      return TRUE;199    else200      return FALSE;201  }202 203  k=Sqrt(n);204  if (k*k==n) {205    if (1+k+n==target_sf)206      return TRUE;207    else208      return FALSE;209  } else {210// n==p1*p2 -> sf==(p1+1)*(p2+1) ?  where p1!=1 && p2!=1211    // if p1==1 || p2==1, it is FALSE because we checked a single prime above.212 213    // sf==(p1+1)*(n/p1+1)214    // sf==n+p1+n/p1+1215    // sf*p1==n*p1+p1^2+n+p1216    // p1^2+(n+1-sf)*p1+n=0217    // x=(-b+/-sqrt(b^2-4ac))/2a218    // a=1219    // x=(-b+/-sqrt(b^2-4c))/2220    // b=n+1-sf;c=n221    b=n+1-target_sf;222// x=(-b+/-sqrt(b^2-4n))/2223    disc=b*b-4*n;224    if (disc<0)225      return FALSE;226    x1=(-b-Sqrt(disc))/2;227    if (x1<=1)228      return FALSE;229    x2=n/x1;230    if (x2>1 && x1*x2==n)231      return TRUE;232    else233      return FALSE;234  }235}236 237U0 PutFactors(I64 n) //For debugging238{239  I64 i,k,sqrt=Ceil(Sqrt(n));240  for (i=2;i<=sqrt;i++) {241    k=0;242    while (!(n%i)) {243      k++;244      n/=i;245    }246    if (k) {247      "%d",i;248      if (k>1)249        "^%d",k;250      '' CH_SPACE;251    }252  }253  if (n!=1)254    "%d ",n;255}256 257class RangeJob258{259  CDoc *doc;260  I64 num,lo,hi,N,sqrt_primes,cbrt_primes;261  Prime *primes;262  CJob *cmd;263} rj[mp_cnt];264 265I64 TestCoreSubRange(RangeJob *r)266{267  I64 i,j,m,n,n2,sf,res=0,range=r->hi-r->lo,268        *sumfacts=MAlloc(range*sizeof(I64)),269        *residue =MAlloc(range*sizeof(I64));270  U16 *pow_cnt =MAlloc(range*sizeof(U16));271  Prime *p=r->primes;272  PowPrime *pp;273  MemSetI64(sumfacts,1,range);274  for (n=r->lo;n<r->hi;n++)275    residue[n-r->lo]=n;276  for (j=0;j<r->sqrt_primes;j++) {277    MemSet(pow_cnt,0,range*sizeof(U16));278    m=1;279    for (i=0;i<p->pow_cnt;i++) {280      m*=p->prime;281      n=m-r->lo%m;282      while (n<range) {283        pow_cnt[n]++;284        n+=m;285      }286    }287    for (n=0;n<range;n++)288      if (i=pow_cnt[n]) {289        pp=&p->pp[i-1];290        sumfacts[n]*=pp->sumfact;291        residue [n]/=pp->n;292      }293    p++;294  }295 296  for (n=0;n<range;n++)297    if (residue[n]!=1)298      sumfacts[n]*=1+residue[n];299 300  for (n=r->lo;n<r->hi;n++) {301    sf=sumfacts[n-r->lo];302    n2=sf-n-1;303    if (n<n2<r->N) {304      if (r->lo<=n2<r->hi && sumfacts[n2-r->lo]-n2-1==n ||305            TestSumFact(n2,sf,r->sqrt_primes,r->cbrt_primes,r->primes)) {306        DocPrint(r->doc,"%u:%u\n",n,sf-n-1);307        res++;308      }309    }310  }311  Free(pow_cnt);312  Free(residue);313  Free(sumfacts);314  return res;315}316 317#define CORE_SUB_RANGE  0x1000318 319I64 TestCoreRange(RangeJob *r)320{321  I64 i,n,res=0;322  RangeJob rj;323  MemCpy(&rj,r,sizeof(RangeJob));324  for (i=r->lo;i<r->hi;i+=CORE_SUB_RANGE) {325    rj.lo=i;326    rj.hi=i+CORE_SUB_RANGE;327    if (rj.hi>r->hi)328      rj.hi=r->hi;329    res+=TestCoreSubRange(&rj);330 331    n=rj.hi-rj.lo;332    lock {progress1+=n;}333 334    Yield;335  }336  return res;337}338 339I64 MagicPairs(I64 N)340{341  F64 t0=tS;342  I64 res=0;343  I64 sqrt_primes,cbrt_primes,num_powprimes,344        i,k,n=(N-1)/mp_cnt+1;345  Prime *primes=PrimesNew(N,&sqrt_primes,&cbrt_primes);346  PowPrime *powprimes=PowPrimesNew(N,sqrt_primes,primes,&num_powprimes);347 348  "N:%u SqrtPrimes:%u CbrtPrimes:%u PowersOfPrimes:%u\n",349        N,sqrt_primes,cbrt_primes,num_powprimes;350  progress1=0;351  *progress1_desc=0;352  progress1_max=N;353  k=2;354  for (i=0;i<mp_cnt;i++) {355    rj[i].doc=DocPut;356    rj[i].num=i;357    rj[i].lo=k;358    k+=n;359    if (k>N) k=N;360    rj[i].hi=k;361    rj[i].N=N;362    rj[i].sqrt_primes=sqrt_primes;363    rj[i].cbrt_primes=cbrt_primes;364    rj[i].primes=primes;365    rj[i].cmd=JobQue(&TestCoreRange,&rj[i],mp_cnt-1-i,0);366  }367  for (i=0;i<mp_cnt;i++)368    res+=JobResGet(rj[i].cmd);369  Free(powprimes);370  Free(primes);371  "Found:%u Time:%9.4f\n",res,tS-t0;372  progress1=progress1_max=0;373  return res;374}375 376MagicPairs(1000000);377