这题看上去是Miller Rabin素数检测(
by _ConveX @ 2018-11-17 10:03:49
这题看上去是Miller Rabin素数检测(
by かなで @ 2018-11-17 10:04:32
@[_ConveX](/space/show?uid=86416) 我去了解一下,谢谢大佬
by goodlearndaydayup @ 2018-11-17 10:05:21
这道题也是强了
by goodlearndaydayup @ 2018-11-17 10:10:11
O(logn)判素数
```cpp
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include <algorithm>
#include <cstdint>
#include <climits>
using namespace std;
std::vector <long long> v;
template <typename T> T mod_add(const T &a,const T &b,const T &m)
{
if (a<m-b) return a+b;
return a-(m-b);
}
template <typename T> T mod_sub(const T &a,const T &b,const T &m)
{
if (a<b) return a+(m-b);
return a-b;
}
template <typename T> T mod_mul(T a,T b,const T &m)
{
if (b>a) swap(a,b);
T r{0};
while (b>0)
{
if (b%2==1) r=mod_add(r,a,m);
a=mod_add(a,a,m);
b/=2;
}
return r;
}
void mul_u128(uint64_t a,uint64_t b,uint64_t &lo,uint64_t &hi)
{
#ifndef __x86_64__
uint64_t a_hi=a>>32;
uint64_t a_lo=a&0xffffffffULL;
uint64_t b_hi=b>>32;
uint64_t b_lo=b&0xffffffffULL;
uint64_t a_hi_b_hi=a_hi*b_hi;
uint64_t a_hi_b_lo=a_hi*b_lo;
uint64_t a_lo_b_hi=a_lo*b_hi;
uint64_t a_lo_b_lo=a_lo*b_lo;
uint64_t middle=a_hi_b_lo+a_lo_b_hi;
hi=a_hi_b_hi+(middle>>32);
lo=a_lo_b_lo+(middle<<32);
if (middle<a_hi_b_lo) hi+=1ULL<<32;
hi+=lo<a_lo_b_lo;
#else
asm("mulq %3" : "=a"(lo), "=d"(hi) : "a"(a), "rm"(b));
#endif
};
uint64_t mul_mod_u64(uint64_t a,uint64_t b,uint64_t m)
{
if (a>=m) a%=m;
if (b>=m) b%=m;
#ifndef __x86_64__
if ((a|b)<1ULL<<32) return (a*b)%m;
uint64_t r=mod_mul(a,b,m);
#else
uint64_t r,u;
asm("mulq %3\n\tdivq %4":"=a"(u), "=&d"(r):"a"(a), "rm"(b), "rm"(m):"cc");
#endif
return r;
}
bool isSprp(uint32_t n,uint32_t a)
{
uint32_t d=n-1;
int s=__builtin_ctz(d);
d>>=s;
uint64_t b=a,r=1;
while (d>0)
{
if (d&1) r=(r*b)%n;
b=(b*b)%n;
d>>=1;
}
if (r==1) return true;
b=n-1;
for (int i=1;i<s;++i)
{
if (r==b) return true;
r=(r*r)%n;
}
return r==b;
}
bool isSprp(uint64_t n,const vector <uint64_t> &v)
{
auto mont_u64_mod_n=[&]() -> uint64_t
{
if (n<=(1ULL<<63))
{
uint64_t res=((1ULL<<63)%n)<<1;
return res<n?res:res-n;
}
return 0ULL-n;
};
auto mont_inv=[&]()->uint64_t
{
uint64_t j,s=1;
uint32_t i,t;
static const uint8_t masks[128]=
{
255,85,51,73,199,93,59,17,15,229,195,89,215,237,203,33,
31,117,83,105,231,125,91,49,47,5,227,121,247,13,235,65,
63,149,115,137,7,157,123,81,79,37,3,153,23,45,11,97,
95,181,147,169,39,189,155,113,111,69,35,185,55,77,43,
129,127,213,179,201,71,221,187,145,143,101,67,217,87,
109,75,161,159,245,211,233,103,253,219,177,175,133,99,
249,119,141,107,193,191,21,243,9,135,29,251,209,207,165,
131,25,151,173,139,225,223,53,19,41,167,61,27,241,239,
197,163,57,183,205,171,1
};
uint8_t mask=masks[(n>>1)&127];
i=(uint32_t)((mask*(s&255))&255);
j=i;
s=(s+n*i)>>8;
i=(uint32_t)((mask*(s&255))&255);
j|=(uint64_t)i<<8;
s=(s+n*i)>>8;
i=(uint32_t)((mask*(s&255))&255);
j|=(uint64_t)i<<16;
s=(s+n*i)>>8;
i=(uint32_t)((mask*(s&255))&255);
j|=(uint64_t)i<<24;
t=(uint32_t)((s+n*i)>>8);
i=(mask*(t&255))&255;
j|=(uint64_t)i<<32;
t=(uint32_t)((t+n*i)>>8);
i=(mask*(t&255))&255;
j|=(uint64_t)i<<40;
t=(uint32_t)((t+n*i)>>8);
i=(mask*(t&255))&255;
j|=(uint64_t)i<<48;
t=(uint32_t)((t+n*i)>>8);
i=(mask*(t&255))&255;
j|=(uint64_t)i<<56;
return j;
};
auto mont_mod_mul=[=](uint64_t a,uint64_t b,uint64_t npi)->uint64_t
{
uint64_t ab_lo,ab_hi,mn_lo,mn_hi;
uint64_t m,u;
int carry;
mul_u128(a,b,ab_lo,ab_hi);
m=ab_lo*npi;
mul_u128(m,n,mn_lo,mn_hi);
carry=ab_lo+mn_lo<ab_lo?1:0;
u=ab_hi+mn_hi+carry;
return (u<ab_hi or u>=n)?u-n:u;
};
if (n%2==0) return n==2;
if (n%3==0) return n==3;
if (n%5==0) return n==5;
if (n%7==0) return n==7;
if (n<121) return n>1;
uint64_t d=n-1;
int s=__builtin_ctzll(d);
d>>=s;
uint64_t npi=mont_inv();
uint64_t r=mont_u64_mod_n();
uint64_t nr=n-r;
for (uint32_t i=0;i<v.size();++i)
{
uint64_t a=mul_mod_u64(v[i],r,n);
uint64_t b=r,k=d;
if (a==0) continue;
while (k>0)
{
if (k&1) b=mont_mod_mul(b,a,npi);
a=mont_mod_mul(a,a,npi);
k>>=1;
}
if (b==r or b==nr) continue;
int j;
for (j=1;j<s;++j)
{
b=mont_mod_mul(b,b,npi);
if (b==r) return false;
if (b==nr) break;
}
if (j==s) return false;
}
return true;
}
bool isPrime(uint32_t n)
{
static const uint32_t bases[]=
{
0x3ce7,0x07e2,0x00a6,0x1d05,0x1f80,0x3ead,0x2907,0x112f,
0x079d,0x050f,0x0ad8,0x0e24,0x0230,0x0c38,0x145c,0x0a61,
0x08fc,0x07e5,0x122c,0x05bf,0x2478,0x0fb2,0x095e,0x4fee,
0x2825,0x1f5c,0x08a5,0x184b,0x026c,0x0eb3,0x12f4,0x1394,
0x0c71,0x0535,0x1853,0x14b2,0x0432,0x0957,0x13f9,0x1b95,
0x0323,0x04f5,0x0f23,0x01a6,0x02ef,0x0244,0x1279,0x27ff,
0x02ea,0x0b87,0x022c,0x089e,0x0ec2,0x01e1,0x05f2,0x0d94,
0x01e1,0x09b7,0x0cc2,0x1601,0x01e8,0x0d2d,0x1929,0x0d10,
0x0011,0x3b01,0x05d2,0x103a,0x07f4,0x075a,0x0715,0x01d3,
0x0ceb,0x36da,0x18e3,0x0292,0x03ed,0x0387,0x02e1,0x075f,
0x1d17,0x0760,0x0b20,0x06f8,0x1d87,0x0d48,0x03b7,0x3691,
0x10d0,0x00b1,0x0029,0x4da3,0x0c26,0x33a5,0x2216,0x023b,
0x1b83,0x1b1f,0x04af,0x0160,0x1923,0x00a5,0x0491,0x0cf3,
0x03d2,0x00e9,0x0bbb,0x0a02,0x0bb2,0x295b,0x272e,0x0949,
0x076e,0x14ea,0x115f,0x0613,0x0107,0x6993,0x08eb,0x0131,
0x029d,0x0778,0x0259,0x182a,0x01ad,0x078a,0x3a19,0x06f8,
0x067d,0x020c,0x0df9,0x00ec,0x0938,0x1802,0x0b22,0xd955,
0x06d9,0x1052,0x2112,0x00de,0x0a13,0x0ab7,0x07ef,0x08b2,
0x08e4,0x0176,0x0854,0x032d,0x5cec,0x064a,0x1146,0x1427,
0x06bd,0x0e0d,0x0d26,0x3800,0x0243,0x00a5,0x055f,0x2722,
0x3148,0x2658,0x055b,0x0218,0x074b,0x2a70,0x0359,0x089e,
0x169c,0x01b2,0x1f95,0x44d2,0x02d7,0x0e37,0x063b,0x1350,
0x0851,0x07ed,0x2003,0x2098,0x1858,0x23df,0x1fbe,0x074e,
0x0ce0,0x1d1f,0x22f3,0x61b9,0x021d,0x4aab,0x0170,0x0236,
0x162a,0x019b,0x020a,0x0403,0x2017,0x0802,0x1990,0x2741,
0x0266,0x0306,0x091d,0x0bbf,0x8981,0x1262,0x0480,0x06f9,
0x0404,0x0604,0x0e9f,0x01ed,0x117a,0x09d9,0x68dd,0x20a2,
0x0360,0x49e3,0x1559,0x098f,0x002a,0x119f,0x067c,0x00a6,
0x04e1,0x1873,0x09f9,0x0130,0x0110,0x1c76,0x0049,0x199a,
0x0383,0x0b00,0x144d,0x3412,0x1b8e,0x0b02,0x0c7f,0x032b,
0x039a,0x015e,0x1d5a,0x1164,0x0d79,0x0a67,0x1264,0x01a2,
0x0655,0x0493,0x0d8f,0x0058,0x2c51,0x019c,0x0617,0x00c2
};
if (n%2==0) return n==2;
if (n%3==0) return n==3;
if (n%5==0) return n==5;
if (n%7==0) return n==7;
if (n<121) return n>1;
uint64_t h=n;
h=((h>>16)^h)*0x45d9f3b;
h=((h>>16)^h)*0x45d9f3b;
h=((h>>16)^h)&0xff;
return isSprp(n,bases[h]);
}
bool isPrime(int32_t n)
{
return isPrime(static_cast<uint32_t>(n));
}
bool isPrime(uint64_t n)
{
static const std::vector <uint64_t> bases[]=
{
{4230279247111683200ULL,14694767155120705706ULL,16641139526367750375ULL},
{2ULL,141889084524735ULL,1199124725622454117ULL,11096072698276303650ULL},
{2ULL,4130806001517ULL,149795463772692060ULL,186635894390467037ULL,3967304179347715805ULL},
{2ULL,123635709730000ULL,9233062284813009ULL,43835965440333360ULL,761179012939631437ULL,1263739024124850375ULL},
{2ULL,325ULL,9375ULL,28178ULL,450775ULL,9780504ULL,1795265022ULL}
};
if (n<7999252175582851ULL)
{
if (n<350269456337ULL)
{
if (n<4294967296ULL) return isPrime(static_cast<uint32_t>(n));
else return isSprp(n,bases[0]);
}
else
{
if (n<55245642489451ULL) return isSprp(n,bases[1]);
else return isSprp(n, bases[2]);
}
}
else
{
if (n<585226005592931977ULL) return isSprp(n, bases[3]);
else return isSprp(n, bases[4]);
}
}
bool isPrime(int64_t n)
{
return isPrime(static_cast<uint64_t>(n));
}
void check(long long n)
{
bool f=false;
if (isPrime((int64_t)n)) goto isp;
for (long long i=2;i*i<=n;++i)
{
if (n%i==0)
{
v.push_back(i);
check(n/i);
f=true;break;
}
}
isp:
if (!f) v.push_back(n);
}
int main()
{
long long n;
scanf("%lld",&n);
if (n==1) return puts("YES")*0;
check(n);
std::sort(v.begin(),v.end());
if (v.size()==1) puts("YES");
else
{
printf("NO\n%lld",v[0]);
for (int i=1;i<v.size();++i) printf("*%lld",v[i]);
puts("");
}
}
```
by 业余门槛 @ 2018-11-17 10:12:48
@[违规用户名XRSq*3EK](/space/show?uid=69922)
by 业余门槛 @ 2018-11-17 10:12:57
蒟蒻表示看不懂
by dinghongyu @ 2018-11-17 10:29:34
@[paul2005](/space/show?uid=95333) %%%~~(虽然好像没有什么用~~
by goodlearndaydayup @ 2018-11-17 13:28:56
@[业余门槛](/user/95333) 折磨牛?
by aaaaaaaawsl @ 2023-08-01 10:38:16