Upd: 写了一点资料. https://pan.baidu.com/s/1GyzysqQUVuUyI8Bsqs9O-g
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef uint64_t u64;
typedef __uint128_t u128;
typedef __int128_t i128;
namespace Timer{
template
std::pair Time(T(*func)(Args...ar),Args...ar){
using hrc=std::chrono::high_resolution_clock;
hrc::time_point start=hrc::now();
T out=func(ar...);
return std::pair(u64(std::chrono::duration_cast(hrc::now()-start)),out);
}
}
inline u128 getint() {
u128 ret=0;
bool ok=0,neg=0;
for(;;) {
int c=getchar();
if(c>='0'&&c<='9') ret=(ret<<3)+ret+ret+c-'0',ok=1;
else if(ok)return neg?0-ret:ret;
else if(c=='-') neg=1;
}
}
void printint(u128 n) {
const u64 ten18=u64(1e18);
if (n>=ten18) printf("%llu%018llu",u64(n/ten18),u64(n%ten18));
else printf("%llu",u64(n));
}
#define rep(i,a,n) for (int i=a;i>64,a_lo=u64(a);
u64 b_hi=b>>64,b_lo=u64(b);
u128 p01=u128(a_lo)*b_lo;
u128 p12=u128(a_hi)*b_lo+u64(p01>>64);
u64 t_hi=p12>>64,t_lo=p12;
p12=u128(a_lo)*b_hi+t_lo;
u128 p23=u128(a_hi)*b_hi+u64(p12>>64)+t_hi;
return u256(u64(p01)|(p12<<64),p23);
}
u128 lo,hi;
};
struct Mont{
Mont(u128 n):mod(n) {
inv=n;
rep(i,0,6) inv*=2-n*inv;
r2=-n%n;
rep(i,0,4) if ((r2<<=1)>=mod) r2-=mod;
rep(i,0,5) r2=mul(r2,r2);
}
u128 reduce(u256 x) const {
u128 y=x.hi-u256::mul128(x.lo*inv,mod).hi;
return i128(y)<0?y+mod:y;
}
u128 reduce(u128 x) const { return reduce(u256(x,0)); }
u128 init(u128 n) const { return reduce(u256::mul128(n,r2)); }
u128 mul(u128 a,u128 b) const { return reduce(u256::mul128(a,b)); }
u128 mod,inv,r2;
};
// the Min-25 montgomery form manipulator
u128 ctz(u128 x){int a=__builtin_ctzll(u64(x>>64))+64,b=__builtin_ctzll(u64(x));return u64(x)?b:a;}
u128 gcd(u128 a,u128 b) {
if (b==0) return a;
int shift=ctz(a|b);
b>>=ctz(b);
while (a) {
a>>=ctz(a);
if (a>=1,a>>=1;
}if(b>a)std::swap(a,b),std::swap(alpha,beta);
while(b&&(a^b)){
a-=b;alpha-=beta;
while(!(a&1)){
if(alpha&1)alpha+=b_or;
alpha>>=1,a>>=1;
}if(b>a)std::swap(a,b),std::swap(alpha,beta);
}
if(a==b)b=0,alpha-=beta,std::swap(alpha,beta);
// putchar(':'),printint(u128(alpha)),putchar(' '),printint(u128(beta)),putchar('\n');
// putchar(':'),printint(u128(-alpha)),putchar(' '),printint(u128(-beta)),putchar('\n');
if(truth)alpha=b_or-alpha;
alpha=alpha%b_or;
if(alpha<0)alpha+=b_or;
if(a!=1)return 0;
return alpha;
}
//invert and gcd
u64 sqrt_approx(u64 x){
u64 approx=sqrt(double(x));
return (approx+x/approx)>>1;
}
u64 sqrt(u64 x){
u64 approx=sqrt(double(x));
u64 apt=(approx+x/approx)>>1;
approx=apt*apt;
if(approx>x)return apt-1;
if(x-approx>=2*apt-1)return apt+1;
return apt;
}
u128 sqrt(u128 r){
if(!(r>>64))return sqrt(u64(r));
int cnt=(((64-__builtin_clzll(u64(r>>64)))+1)|1)^1;
u128 approx=u128(sqrt_approx(u64(r>>cnt)))<<(cnt/2);
approx=(approx+r/approx)>>1;
u128 apt=u128(u64(approx))*u128(u64(approx));
return approx-((r-apt)>>127);
}
// fast int128 square root
#define ModularManipulate \
u128 n=Modu->mod; \
const auto add=[&] (u128 x,u128 y) { return (x+=y)>=n?x-n:x; }; \
const auto sub=[&] (u128 x,u128 y) { return i128(x-=y)<0?x+n:x; }; \
const auto mul=[&] (u128 x,u128 y) { return Modu->mul(x,y); }; \
const auto get=[&] (u128 x) { return Modu->reduce(x); }; \
const auto set=[&] (u128 x) { return Modu->init(x); }; \
const auto dbl=[&] (u128 x) { return (x<<=1)>=n?x-n:x; };
u128 invert(u128*inv,u128*lis,int len,Mont*Modu){
ModularManipulate
for(int i=1;i=0;i-=2){
if(f)ca[0]=mul(ca[0],ca[0]),ca[0]=mul(ca[0],ca[0]);
int q=(exp>>i)&3;
if(q)f=1,ca[0]=mul(ca[0],ca[q]);
}return ca[0];
}
u128 Double(affine*p1,int len,Mont*Modu){
ModularManipulate
u128*inv=tempui[0],*invr=tempui[1];
for(int i=0;i>=1;
}return res;
}
#define prr(x) printpoints(x,len,Modu)
void printpoints(affine*af,int len,Mont*Modu){
ModularManipulate
printf("Count:\n%d\n[",len);
for(int i=0;i>=2;
// prr(p1);
while(Na!=1){
int op=Na&3;
u128 k=Double(p1,len,Modu);
// puts("*2");
// prr(p1);
if(k)return k;
if(op==1)k=Add(tem,p1,len,Modu);//,puts("+1"),prr(p1),prr(tem);
else if(op==3)k=Sub(tem,p1,len,Modu);//,puts("-1"),prr(p1),prr(tem);
if(k)return k;
Na>>=2;
}return 0;
}
u128 InitPoints(u128*param,affine*points,int len,Mont*Modu){
ModularManipulate
u128 five=set(5),two=set(2),one=set(1);
for(int cn=0;cn>1,rt=0;
while(rt=30)st-=30,++rt;
if(st>=30)st-=30,++rt;
}
}
void PrintMask(u32*a,u32 len){
printf("Mask of len %u\n",len*60);
for(u32 i=0;i main(ull ma){
ull tma,tmx;
tma=(ma-1)/60+1;
tmx=tma*60;//upper limit
u32*sieve=new u32[tma];// getting a sieve ready
u32*maske=new u32[7429];
std::fill(sieve,sieve+tma,mask);
for(int i=0;i<6;++i)
Apply_mask(sieve,maske,tma,Gen_mask(maske,i));
ull preseg=std::min(tmx,ull(sqrt(double(ma))/60)+1);
u32 j=61;
for(;ull(j)*j<=preseg*60;j+=2){
u32 v=j/60,u=(j%60)>>1;
if(!(sieve[v]&(1<>1;
while(rt=30)st-=30,++rt;
}
pr[prl][0]=v;
pr[prl][1]=u;
pr[prl][2]=rt;
pr[prl][3]=st;
prl++;
}
} // Non-segmented sieve core
if(preseg==tmx)goto end;
for(u32 segl=preseg;segl>1;
if(!(sieve[v]&(1<>1;
pr[prl][0]=v;
pr[prl][1]=u;
pr[prl][2]=rt;
pr[prl][3]=st;
prl++;
}
}
for(int i=0;i=30)st-=30,++rt;
}
pr[i][0]=v;
pr[i][1]=u;
pr[i][2]=rt;
pr[i][3]=st;
}
}
end:
sieve[0]=pr60_m;
std::vector ret;
ret.push_back(2);
for(u32 i=0;i primes){
u128*param=tempui[2];
Mont Mod(N);
Mont*Modu=&Mod;
ModularManipulate
for(int i=0;iSmoothBound)break;
u64 t=i,g=SmoothBound/i;
while(t<=g)t*=i;
ret=FastMultiply(plist,t,curve_count,Modu);
// printf("Mult %llu\n",t);
// printpoints(plist,curve_count,&Mod);
if(ret)return ret;
}
return 1;
}
void Test(u128 N,int SmoothBound,int curve_count,std::vector primes){
u128*param=tempui[2];
affine*plist=tempaff[2];
affine*plist2=tempaff[3];
Mont Mod(N);
Mont*Modu=&Mod;
ModularManipulate
for(int i=0;i pr=Sieve::main(1000000);
u128 p=factor(inp,50000,160,pr);
u128 q=inp/p;
if(q