一、整数分块——
求从1到n的n/i的和,即求。
代码段:
ll ans=0;
for(int l=1;l<=n;l=r+1)
{
r=n/(n/l);
ans+=(r-l+1)*(n/l);
}
二、欧几里得——
用于求两个数的最大公约数,也称辗转相除法。
代码段:
ll gcd(ll a,ll b)
{
if(!b) return a;
return gcd(b,a%b);
}(有模取模)
扩展欧几里得:用于求逆元,求同余方程,求ax+by=gcd(x,y)。
代码段:
ll exgcd(ll a,ll b,ll &x, ll &y)
{//a的逆元对b取模
if(!b)
{
x=1;
y=0;//特解情况
return a;
}
ll other,r=exgcd(b,a%b,x,y);
other =x;
x=y;
y=other-a/b*y;//通解
return r;
}
三、逆元——
求逆元可用扩展欧几里得,也可以用费马小定理,以下是费马小定理求解:
ll Inverse(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1) ans=ans*a;//奇数
b>>=1;
a=a*a;//偶数
}
return ans;
}(有模取模)
四、欧拉定理——
五、二分乘与二分幂
ll midmul(ll a,ll b,ll mod)
{//二分乘
if(b==0) return 0;
if(b&1) return (a+midmul((a<<1)%mod,b>>1)%mod)%mod;//奇数
else return midmul((a<<1)%mod,b>>1)%mod;//偶数
}
ll midpow(ll a,ll b,ll mod)
{//二分幂
if(b==0) return 1;
if(b&1) return a*midpow(a*a%mod,b>>1,mod)%mod;//这里的乘法用二分乘更好,直接乘大数据容易出错
else return return midpow(a*a%mod,b>>1,mod)%mod;
}
六、Lucas定理
用于求组合数,根据Lucas定理有: %mod= * %mod.
代码段:
ll C(ll a,ll b, ll mod)
{//Ca_b=a!/(b!*(a-b)!)
ll ans=1;
ll sum=1;
for(int i=0;i<b;i++)
{
sum=sum*(a-i)%mod;//a*(a-1)*(a-2)*(a-3)*……*(a-b+1)=a!/(a-b)!
ans=ans*(i+1)%p;//b!
}
ans=Inverse(ans,mod-2,mod);
return sum*ans%mod;
}
ll Lucas(ll a,ll b,ll mod)
{
if(!b) return 1;
return Lucas(a/mod,b/mod,mod)*C(a%mod,b%mod,mod)%mod;
}
不对的地方欢迎指正