# 初阶

## 扩展欧拉

$$k\ge\varphi(m)$$时，$$b^k\equiv b^{k\%\varphi(m)+\varphi(m)}(\bmod m$$)

## 扩展BSGS

https://www.cnblogs.com/flashhu/p/9737769.html

## 扩展Lucas

$$n!$$中所有$$p$$因子提出来，因子个数$$\sum\limits_{i=1}\lfloor\frac{n}{p^i}\rfloor$$

#include<bits/stdc++.h>
#define LL long long
#define R register LL
using namespace std;
LL n,m,YL,F[1000009];
void exgcd(R a,R b,R&x,R&y){
if(!b){x=1;y=0;return;}
exgcd(b,a%b,y,x);y-=a/b*x;
}
inline LL qpow(R b,R k,R p){
R a=1;
for(;k;k>>=1,b=b*b%p)
if(k&1ll)a=a*b%p;
return a;
}
LL fac(R n,R p,R k){
return n?qpow(F[k],n/k,k)*F[n%k]%k*fac(n/p,p,k)%k:1;
}
inline LL inv(R n,R p){
R x,y;exgcd(n,p,x,y);
return x<=0?x+p:x;
}
inline LL cnt(R n,R p){
R k=0;
for(n/=p;n;n/=p)k+=n;
return k;
}
inline LL C(R n,R m,R p,R k){
for(R i=F[0]=1;i<=k;++i)
F[i]=i%p?F[i-1]*i%YL:F[i-1];
return fac(n,p,k)*inv(fac(m,p,k),k)%k*inv(fac(n-m,p,k),k)%k*qpow(p,cnt(n,p)-cnt(m,p)-cnt(n-m,p),k)%k;
}
inline LL CRT(R a,R p){
return YL/p*inv(YL/p,p)%YL*a%YL;
}
int main(){
cin>>n>>m>>YL;
R now=YL,lim=sqrt(YL),ans=0;
for(R p=2;p<=lim;++p){
if(now%p)continue;
R k=1;while(now%p==0)now/=p,k*=p;
ans=(ans+CRT(C(n,m,p,k),k))%YL;
lim=sqrt(now);
}
if(now>1)ans=(ans+CRT(C(n,m,now,now),now))%YL;
cout<<ans<<endl;
return 0;
}


# 进阶

## Miller-Rabin&Pollard-Rho

upd:模数为long long级别的乘法取模原理

#include<bits/stdc++.h>
#define SL __int128
#define LL long long
#define RG register
#define R RG int
using namespace std;
LL t,n,ans;
inline LL Mul(LL a,LL b,LL p){//㧟的玄学乘法取模
LL d=((long double)a/p*b+1e-8);
LL r=a*b-d*p;
return r<0?r+p:r;
}
inline LL Gcd(LL a,LL b){//㧟的builtin辗转相减
if(!a||!b)return a|b;
int t=__builtin_ctzll(a|b);
a>>=__builtin_ctzll(a);
do{
b>>=__builtin_ctzll(b);
if(a>b)swap(a,b);
b-=a;
}while(b);
return a<<t;
}
inline LL Qpow(LL b,LL k,LL p,LL a=1){
for(;k;k>>=1,b=(SL)b*b%p)
if(k&1ll)a=(SL)a*b%p;
return a;
}
inline LL MR(LL n){
if(n==2)return 1;
if(n==1||(1&n)==0)return 0;
static int a[]={2,3,7,13,61,24251};
LL u=n-1,x,y;R k=0;
while((1&u)==0)u>>=1,++k;
for(R i=0;i<6&&a[i]<n;++i){
x=Qpow(a[i],u,n);
for(R j=0;j<k;++j,x=y){
y=(SL)x*x%n;
if(y==1&&x!=1&&x!=n-1)return 0;
}
if(x!=1)return 0;
}
return 1;
}
inline LL F(LL a,LL c,LL n){
LL t=Mul(a,a,n)+c;
return t<n?t:t-n;
}
inline LL PR(LL n){
if((1&n)==0)return 2;
LL c=rand(),a=rand(),b=a,g;
do{
a=F(a,c,n);b=F(F(b,c,n),c,n);
g=Gcd(n,abs(a-b));
if(g!=1&&g!=n)return g;
}while(a!=b);
return g;
}
void find(LL n){
if(n==1||n<=ans)return;
if(MR(n)){ans=max(ans,n);return;}
LL d=n;
while(d==n)d=PR(n);
while(n%d==0)n/=d;
find(n);find(d);
}
int main(){
srand(time(NULL));
cin>>t;
while(t--){
cin>>n;ans=1;find(n);
if(ans==n)puts("Prime");
else cout<<ans<<'\n';
}
return 0;
}


## 狄利克雷卷积&杜教筛

$$\mu*\textbf1=\epsilon\Leftrightarrow\sum\limits_{d|n}\mu(d)=[n==1]$$
$$\varphi*\textbf1=\textbf{id}\Leftrightarrow\sum\limits_{d|n}\varphi(d)=n$$
$$\mu*\textbf{id}=\varphi\Leftrightarrow\sum\limits_{d|n}\frac{n}{d}\mu(d)=\varphi(n)$$
$$\textbf1*\textbf1=\textbf{d};\textbf{d}*\textbf1=\sigma$$（感觉还有很多都是可以相互推出来的）

$$\sum\limits_{i=1}^nF(i)=\sum\limits_{i=1}^n\sum\limits_{xy=i}f(x)g(y)=\sum\limits_{y=1}^ng(y)\sum\limits_{x=1}^{\lfloor\frac{n}{y}\rfloor}f(x)=g(1)S(x)+\sum\limits_{y=2}^ng(y)S(\lfloor\frac n y\rfloor)$$
$$g(1)S(x)=\sum\limits_{i=1}^nF(i)-\sum\limits_{y=2}^ng(y)S(\lfloor\frac n y\rfloor)$$

#include<bits/stdc++.h>
#define LL long long
#define UI unsigned int
#define RG register
#define R RG int
using namespace std;
const LL N=2147483648,M=1.7e6,L=2000;
int pr[M],cnt;bool vis[M];
struct Dat{LL p;int u;}s[M],t[L];
Dat&S(UI n){
if(n<M)return s[n];
UI x=N/n;if(vis[x])return t[x];vis[x]=1;
Dat&ans=t[x];
ans.p=(LL)n*(n+1)>>1;ans.u=1;
for(UI l=2,r;l<=n;l=r+1){
r=n/(n/l);Dat&ret=S(n/l);
ans.p-=(r-l+1)*ret.p;
ans.u-=(r-l+1)*ret.u;
}
return ans;
}
int main(){
s[1]=(Dat){1,1};vis[1]=1;
for(R i=2;i<M;++i){
if(!vis[i])s[pr[++cnt]=i]=(Dat){i-1,-1};
for(R j=1,x;j<=cnt&&(x=i*pr[j])<M;++j){
vis[x]=1;
if(i%pr[j]==0){s[x].p=s[i].p*pr[j];break;}
s[x].p=s[i].p*(pr[j]-1);s[x].u=-s[i].u;
}
s[i].p+=s[i-1].p;s[i].u+=s[i-1].u;
}
memset(vis,0,M);
R t,n;cin>>t;
while(t--){
cin>>n;
Dat ret=S(n);
cout<<ret.p<<' '<<ret.u<<endl;
memset(vis,0,L);
}
return 0;
}


## Min_25筛

yyb巨佬告诉我这是今年新鲜出炉的筛法，吊打了某洲阁筛（话说写这句话的时候是今年的最后一天了）

https://www.cnblogs.com/cjyyb/p/10169190.html
https://www.cnblogs.com/cjoieryl/p/9403579.html
https://www.cnblogs.com/zhoushuyu/p/9187319.html
https://www.cnblogs.com/cx233666/p/10173977.html
https://www.cnblogs.com/GuessYCB/p/10061411.html （都是高级操作）

### Step1

$$\sqrt N$$范围的质数筛出来，记为$$P$$。预处理质数的函数前缀和$$fs$$

$$g(n,j)$$$$x\in[1,n]$$中满足$$x\in P$$$$x$$的最小质因子小于$$P_j$$$$f(x)$$之和

### Step2

$$S(n,j)$$$$x\in[1,n]$$中满足$$x$$的最小质因子大于等于$$P_j$$$$f(x)$$之和（注意和$$g$$的区别）

$$S(n,j)$$时，分质数和合数算贡献

$$\sum\limits_{k=j}^{P_k^2\le n}\sum\limits_{e=1}^{P_k^{e+1}\le n}S(\lfloor\frac{n}{P_k^e}\rfloor,k+1)f(P_k^e)+f(P_k^{e+1})$$
LOJ6053 简单的函数

#include<bits/stdc++.h>
#define LL long long
#define RG register
#define R RG LL
using namespace std;
const LL N=2e5+9,YL=1e9+7;
LL n,Sq,p,m,pr[N],id1[N],id2[N],w[N],fx[N],gx[N],g1[N];
bool np[N];
inline LL Getid(R x){
return x<=Sq?id1[x]:id2[n/x];
}
void Sieve(){
for(R i=2;i<=Sq;++i){
if(np[i])continue;
pr[++p]=i;fx[p]=(fx[p-1]+i)%YL;
for(R j=i*i;j<=Sq;j+=i)np[j]=1;
}
}
LL S(R n,R j){
if(n<=1||pr[j]>n)return 0;
R x=Getid(n);
R ret=(gx[x]-fx[j-1]-g1[x]+j-1+2*YL)%YL;
for(R k=j;k<=p&&pr[k]*pr[k]<=n;++k){
R p1=pr[k],p2=p1*p1;
for(R e=1;p2<=n;++e,p1=p2,p2*=pr[k])
ret=(ret+S(n/p1,k+1)*(pr[k]^e)+(pr[k]^(e+1)))%YL;
}
return ret;
}
int main(){
cin>>n;
if(n==1)return puts("1"),0;
Sq=sqrt(n);Sieve();
for(R i=1,j;i<=n;i=j+1){
R x=w[++m]=n/i;j=n/x;
(x<=Sq?id1[x]:id2[n/x])=m;
gx[m]=(x+2)%YL*((x-1)%YL)%YL*((YL+1)>>1)%YL;
g1[m]=(x-1)%YL;
}
for(R j=1;j<=p;++j)
for(R i=1;i<=m&&pr[j]*pr[j]<=w[i];++i){
R x=Getid(w[i]/pr[j]);
gx[i]=((gx[i]-pr[j]*(gx[x]-fx[j-1]))%YL+YL)%YL;
g1[i]=(g1[i]-g1[x]+j-1+YL)%YL;
}
return cout<<S(n,1)+3<<endl,0;
}

posted @ 2018-12-28 14:33  Flash_Hu  阅读(735)  评论(2编辑  收藏  举报