bool vis[MAXN];
ll prime[MAXN],cnt;//素数个数;
ll mu[MAXN],mus[MAXN];
void getMus(){//线性筛求莫比乌斯函数1-N的函数值
int N=MAXN;
//memset(mu,0,sizeof(mu));
memset(vis,0,sizeof(vis));
mu[1] = 1;
cnt = 0;
for(ll i=2; i<=N; ++i){
if(!vis[i]){prime[++cnt] = i;mu[i] = -1;}
for(int j=1;j<=cnt&&i*prime[j]<=N;++j){
vis[i*prime[j]] = 1;
if(i%prime[j]) mu[i*prime[j]] = -mu[i];
else{
mu[i*prime[j]] = 0;
break;
}
}
}
for(int i=1;i<=N;i++)mus[i]=mus[i-1]+mu[i];
}
ll phi[MAXN],phis[MAXN];
void getPhis(){//线性筛求欧拉函数1-N的函数值
int N=MAXN;
//memset(phi,0,sizeof(phi));
memset(vis,0,sizeof(vis));
phi[1] = 1;
cnt = 0;
for(ll i=2; i<=N; ++i){
if(!vis[i]){prime[++cnt] = i;phi[i] = i-1;}
for(int j=1;j<=cnt&&i*prime[j]<=N;++j){
vis[i*prime[j]] = 1;
if(i%prime[j]) phi[i*prime[j]] = phi[i]*(prime[j]-1);
else{
phi[i*prime[j]] = phi[i]*prime[j];
break;
}
}
}
for(int i=1;i<=N;i++)phis[i]=phis[i-1]+phi[i];
}
void phimu(){//同时求莫比乌斯与欧拉函数值
int N=MAXN;
memset(phi,-1,sizeof(phi));
memset(mu,-1,sizeof(mu));
cnt=0;
phi[0]=mu[0]=0;phi[1]=mu[1]=1;
for(ll i=2;i<=N;++i){
if(phi[i]<0){
prime[++cnt]=i;
phi[i]=i-1;//质数的欧拉函数值为p-1
mu[i]=-1;//质数的莫比乌斯函数值为-1
}
for(ll j=1;j<=cnt&&i*prime[j]<=N;++j){
if(i%prime[j]){
phi[i*prime[j]] = phi[i]*(prime[j]-1);
mu[i*prime[j]] = -mu[i];
}
else {
phi[i*prime[j]] = phi[i]*prime[j];
mu[i*prime[j]] = 0;
break;
}
}
}
for(ll i=1;i<=N;i++){
phis[i]=phis[i-1]+phi[i];
mus[i]=mus[i-1]+mu[i];
}
}
ll v[MAXN];
void primes(long long n){//线性筛打素数表
memset(v,0,sizeof(v));
cnt=0;
for(ll i=2;i<=n;++i){
if(v[i]==0){v[i]=i;prime[++cnt]=i;}//v[i]记录i自身的最小因子
for(int j=1;j<=cnt;++j){
if(prime[j]>v[i]||prime[j]>n/i)break;//i有比prime[j]更小的质因子,或者超出范围,停止循环
v[i*prime[j]]=prime[j];//prime[j]是合数i*prime[j]的最小因子
}
}
}
int getMu(long long n){//筛法求大数(>1e7)单点莫比乌斯函数值
long long N=10000000;
if(n<=N)return mu[n];
int k=1;
for(long long i=2;i*i<=n;i++){
if(n%i==0){
if(n%(i*i)==0)return 0;
k*=-1,n/=i;
}
}
if(n>1)k*=-1;
return k;
}
long long getPhi(long long n){//求n欧拉函数值 单个点
long long ans=n;
for(ll i=2;i*i<=n;++i)//O(n)算法
if(n%i==0){
ans=ans/i*(i-1);//ans=ans-ans/n;
while(n%i==0)n/=i;
}
if(n>1)ans=ans/n*(n-1);//ans=ans-ans/n;
return ans;
}
long long getPhi(long long n){//已有素数表快速求n欧拉函数值 单个点
long long ans=1;
for(ll i=1;i<=cnt&&prime[i]*prime[i]<=n;i++){
if(n%prime[i]==0){
ans*=(prime[i]-1);
n=n/prime[i];
while(n%prime[i]==0){
ans*=prime[i];
n/=prime[i];
}
}
}
if(n>1)ans*=n-1;
return ans;
}
long long slowmul(long long a,long long b ,long long m){//慢速乘法取模 a*b%m
a%=m;
long long k=0;
while(b){
if(b&1){
k=k+a;
if(k>=m)k=k-m;
}
a=a<<1;
if(a>=m)a=a-m;
b=b>>1;
}
return k;
}
long long quickpowmod(long long a,long long b ,long long m){//快速幂取模 a^b%m
long long k=1L;a%=m;
while(b>0){
if(b&1)k=slowmul(k,a,m);//如果会超ll 使用慢速乘
b=b>>1;
a=slowmul(a,a,m);//如果会超ll 使用慢速乘
}
return k;
}
vector factor;
void factors(ll n){//试除法求n的约数集合
factor.clear();
for(ll i=1;i*i<=n;++i){
if(n%i==0){
factor.push_back(i);
if(i!=n/i)factor.push_back(n/i);
}
}
}
//整除分块模板
for(int l=1,r;l<=n;l=r+1)
{
r=n/(n/l);
ans+=(r-l+1)*cal(n/l);
}
//杜教筛模板
map _phi;
long long CalcPhi(long long n){
map::iterator ite;
if(nsecond;
long long last, ans = n * (n + 1) >> 1;//注意爆longlong 与分数取模
for(long long i = 2; i <= n; i = last + 1) {
last = n / (n / i);
ans -= (last - i + 1) * CalcPhi(n / i);
}
return _phi[n] = ans;//记忆化
}
map _mu;
long long CalcuMu(long long n){
map::iterator ite;
if(nsecond;
long long last, ans = 1;
for(long long i = 2; i <= n; i = last + 1) {
last = n / (n / i);
ans -= (last - i + 1) * CalcuMu(n / i);
}
return _mu[n] = ans;//记忆化
}
米勒罗宾素性测试
// 18位素数:154590409516822759
// 19位素数:2305843009213693951 (梅森素数)
// 19位素数:4384957924686954497
long long prime[6] = {2, 3, 5, 233, 331};
long long qmul(long long x, long long y, long long mod) { // 乘法防止溢出, 如果p * p不爆long long的话可以直接乘; O(1)乘法或者转化成二进制加法
return (x * y - (long long)(x / (long double)mod * y + 1e-3) *mod + mod) % mod;
/*
long long ret = 0;
while(y) {
if(y & 1)
ret = (ret + x) % mod;
x = x * 2 % mod;
y >>= 1;
}
return ret;
*/
}
long long qpow(long long a, long long n, long long mod) {
long long ret = 1;
while(n) {
if(n & 1) ret = qmul(ret, a, mod);
a = qmul(a, a, mod);
n >>= 1;
}
return ret;
}
bool Miller_Rabin(long long p) {
if(p < 2) return 0;
if(p != 2 && p % 2 == 0) return 0;
long long s = p - 1;
while(! (s & 1)) s >>= 1;
for(int i = 0; i < 5; ++i) {
if(p == prime[i]) return 1;
long long t = s, m = qpow(prime[i], s, p);
while(t != p - 1 && m != 1 && m != p - 1) {
m = qmul(m, m, p);
t <<= 1;
}
if(m != p - 1 && !(t & 1)) return 0;
}
return 1;
}
大素数判定和素因子分解(转自kuangbin)
https://www.cnblogs.com/kuangbin/archive/2012/08/19/2646396.html
#include
#include
#include
#include
#include
#include
using namespace std;
//****************************************************************
// Miller_Rabin 算法进行素数测试
//速度快,而且可以判断 <2^63的数
//****************************************************************
const int S=20;//随机算法判定次数,S越大,判错概率越小
//计算 (a*b)%c. a,b都是long long的数,直接相乘可能溢出的
// a,b,c <2^63
long long mult_mod(long long a,long long b,long long c)
{
a%=c;
b%=c;
long long ret=0;
while(b)
{
if(b&1){ret+=a;ret%=c;}
a<<=1;
if(a>=c)a%=c;
b>>=1;
}
return ret;
}
//计算 x^n %c
long long pow_mod(long long x,long long n,long long mod)//x^n%c
{
if(n==1)return x%mod;
x%=mod;
long long tmp=x;
long long ret=1;
while(n)
{
if(n&1) ret=mult_mod(ret,tmp,mod);
tmp=mult_mod(tmp,tmp,mod);
n>>=1;
}
return ret;
}
//以a为基,n-1=x*2^t a^(n-1)=1(mod n) 验证n是不是合数
//一定是合数返回true,不一定返回false
bool check(long long a,long long n,long long x,long long t)
{
long long ret=pow_mod(a,x,n);
long long last=ret;
for(int i=1;i<=t;i++)
{
ret=mult_mod(ret,ret,n);
if(ret==1&&last!=1&&last!=n-1) return true;//合数
last=ret;
}
if(ret!=1) return true;
return false;
}
// Miller_Rabin()算法素数判定
//是素数返回true.(可能是伪素数,但概率极小)
//合数返回false;
bool Miller_Rabin(long long n)
{
if(n<2)return false;
if(n==2)return true;
if((n&1)==0) return false;//偶数
long long x=n-1;
long long t=0;
while((x&1)==0){x>>=1;t++;}
for(int i=0;i=n)p=Pollard_rho(p,rand()%(n-1)+1);
findfac(p);
findfac(n/p);
}
int main()
{
long long n;
while(scanf("%I64d",&n)!=EOF)
{
tol=0;
findfac(n);
for(int i=0;i