一、分解质因数
1. 试除法
模板:复杂度 O(sqrt(n))
void solve(int n){
for(int i=2;i<=n/i;i++){
if(n%i==0){
int sum=0;
while(n%i==0){
n/=i;
sum++;
}
cout<<i<<" "<<sum<<endl;
}
}
if(n>1) cout<<n<<" "<<1<<endl;
}
二、筛质数
1.普通筛
模板:复杂度 O(n*logn)
int n,prime[N],p[N],cnt;
void solve(){
for(int i=2;i<=n;i++){
if(prime[i]==0){
p[++cnt]=i;
for(int j=2;j*i<=n;j++) prime[j*i]=1;
}
}
}
2.线性筛
模板:复杂度 O(n)
int n,prime[N],p[N],cnt;
void solve(){
for(int i=2;i<=n;i++){
if(prime[i]==0) p[++cnt]=i;
for(int j=1;j<=cnt&&i*p[j]<=n;j++){
prime[i*p[j]]=1;
if(i%p[j]==0) break;
}
}
}
三、快速幂
模板:
LL qp(LL a,LL b){//是求a的b次方
LL ans=1ll%mod,base=a%mod;//ans为答案,base为a^(2^n)
while(b>0){
if(b&1ll) ans=(ans*base)%mod;
base=(base*base)%mod;
b>>=1ll;
}
return ans;
}
四、逆元
同余不满足除法,即 (a/b) % p != (a % p) / (b % p) ;
这里主要说明分数取模的方法,对于 (a/b) % p,可以先求出 b 在 % p 下的逆元,然后乘上a,再mod p,就是分数取模的值了;
逆元的求解方法:
1.费马小定理
当 p 为素数,且 a 为正整数,并且 a,p 互质,则逆元就等于
a
p
−
2
a^{p-2}
ap−2%p;
所以只要运用快速幂就可以;
模板:
LL qp(LL a,LL b){//是求a的b次方
LL ans=1ll%mod,base=a%mod;//ans为答案,base为a^(2^n)
while(b>0){
if(b&1ll) ans=(ans*base)%mod;
base=(base*base)%mod;
b>>=1ll;
}
return ans;
}
int main(){
string s1,s2;cin>>s1>>s2;
LL a=0,b=0;
int len1=s1.length(),len2=s2.length();
for(int i=0;i<len1;i++){
a*=10;a+=s1[i]-'0';
a%=mod;
}
for(int i=0;i<len2;i++){
b*=10;b+=s2[i]-'0';
b%=mod;
}
if(b==0) cout<<"Angry!"<<endl;
else{
LL ans=a*qp(b,mod-2ll);
cout<<(ans%mod+mod)%mod<<endl;
}
return 0;
}
五、拓展欧几里得
扩展欧几里得是用来求 ax + by = gcd(a,b) 中的未知数的,那么如果等式不等于 gcd(a,b) 怎么办呢?
比如:ax + by = z,记住一点就是等式有解必须保证 z%gcd(a,b)==0,所以可以先利用扩展求出 ax + by = gcd(a,b) 的解,然后乘上 z/gcd(a,b) 就可以;
模板题:洛谷·P1082 同余方程
模板:
LL x,y;//方程的解
void exgcd(LL a,LL b){
if(b==0){
x=1,y=0;
return;
}
exgcd(b,a%b);
LL tx=x;
x=y;
y=tx-a/b*y;
}
int main(){
LL a,b;cin>>a>>b;
exgcd(a,b);
x=(x%b+b)%b;//求出来的x一定满足方程,但不一定是最小解
cout<<x<<endl;
return 0;
}
六、组合数
求组合数 C ( n , m ) C(n,m) C(n,m);
模板:
ll qp(ll a,int b){
ll ans=1ll%mod;
while(b>0){
if(b&1) ans=(ans*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return ans;
}
ll fact[N],inv[N];
ll C(ll x, ll y){
if(x<y||y<0) return 0;
return fact[x]*inv[y]%mod*inv[x-y]%mod;
}
void init(){
fact[0]=1;
for(int i=1;i<N;i++) fact[i]=fact[i-1]*i%mod;
inv[N-1]=qp(fact[N-1],mod-2);
for(int i=N-2;i>=0;i--) inv[i]=inv[i+1]*(i+1)%mod;
}