#pragma GCC optimize(2)
逆元板子块
先来一个线性求逆元
#include
using namespace std;
typedef long long ll;
const int maxn=100005;
const int mod=(int)1e9+7;
ll inv[maxn],a[maxn],n;
int main(){
inv[1]=1;
for(int i=2;i
也可以递归求 复杂度为logn
ll inv(ll n){
if(n==1)
return 1;
return (mod-mod/n)*(inv(mod%n))%mod;
}
再加上一个阶乘的线性求逆元板子
fac[0]=fac[1]=1;
for(ll i=2;i=0;i--)
inv_fac[i]=inv_fac[i+1]*(i+1)%mod;
辗转相除法求逆元1
#include
using namespace std;
typedef long long ll;
const int mod=1e9+7;
ll exgcd(ll a,ll b,ll &x,ll &y){
if(b==0){
x=1;
y=0;
return a;
}
ll r=exgcd(b,a%b,x,y);
ll t=x%mod;
x=y%mod;
y=((t-a/b*y)%mod+mod)%mod;
return r;
}
//求2对于1e9+7的逆元就是 exgcd(2,1e9+7,x,y),其中x的值就是inv2,
int main(){
ll a;
while(~scanf("%lld",&a)){
ll x=1,y=1;
exgcd(a,mod,x,y);
printf("%lld\n",x);
}
return 0;
}
辗转相除法求逆元2
#include
using namespace std;
typedef long long ll;
const int mod=1e9+7;
ll extend_gcd(ll a,ll b,ll &x,ll &y) {
if(a==0&&b==0) return -1;//无最大公约数
if(b==0){x=1;y=0;return a;}
ll d=extend_gcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
//*********求逆元素*******************
//ax = 1(mod n)
ll mod_reverse(ll a,ll n) {
ll x,y;
ll d=extend_gcd(a,n,x,y);
if(d==1) return (x%n+n)%n;
else return -1;
}
int main(){
ll a;
while(~scanf("%lld",&a)){
ll x=1,y=1;
ll ans=mod_reverse(a,mod);
printf("%lld\n",ans);
}
return 0;
}
再来个线性求素数的板子
#include
using namespace std;
const int maxn=1000005;
int prime[maxn],numprime,vis[maxn];
void init(){
for(int i=2;i
组合数
#include
using namespace std;
typedef long long ll;
const int mod=998244353;
const int maxn=200005;
ll fac[maxn],inv_fac[maxn],n,m,k;
ll quick(ll a,ll b){
ll ans=1;
while(b){
if(b&1) ans=ans*a%mod;
a=a*a%mod;
b/=2;
}
return ans;
}
void init(){
inv_fac[0]=fac[0]=1,fac[1]=inv_fac[1]=1;
for(int i=2;i=0;i--)
inv_fac[i]=inv_fac[i+1]*(i+1)%mod;
}
ll C(ll n,ll m){
if(n<0||m<0||m>n) return 0;
if(n==m||m==0) return 1;
return fac[n]*inv_fac[n-m]%mod*inv_fac[m]%mod;
}
int main(){
init();
int t;
cin>>t;
while(t--){
}
return 0;
}
快速读入的板子
ll read(){
ll ans=0; char last=' ',ch=getchar();
while(ch<'0' || ch>'9')last=ch,ch=getchar();
while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
if(last=='-')ans=-ans; return ans;
}
大神那里搜集来的素数判定 Miller_Rabin算法板子
#include
using namespace std;
typedef long long ll;
const int times=20;
int number=0;
mapm;
ll Random(ll n){ //生成[ 0 , n ]的随机数
return ((double)rand()/RAND_MAX*n+0.5);
}
ll quick_mul(ll a,ll b,ll mod){//快速计算 (a*b) % mod
ll ans=0;
while(b){
if(b&1){
b--;
ans=(ans+a)%mod;
}
b/=2;
a=(a+a)%mod;
}
return ans;
}
ll quick(ll a,ll b,ll mod){
ll ans=1;
while(b){
if(b&1) ans=quick_mul(ans,a,mod);
b/=2;
a=quick_mul(a,a,mod);
}
return ans;
}
int witness(ll a,ll n){//miller_rabin算法的精华
//用检验算子a来检验n是不是素数
ll tem=n-1;
int j=0;
while(tem%2==0){
tem/=2;
j++;
}//将n-1拆分为a^r * s
ll x=quick(a,tem,n);//得到a^r mod n
if(x==1||x==n-1) return 1; //余数为1则为素数
while(j--){//否则试验条件2看是否有满足的 j
x=quick_mul(x,x,n);
if(x==n-1) return 1;
}
return 0;
}
int miller_rabin(ll n){//检验n是否是素数
if(n==2)
return 1;
if(n<2||n%2==0)
return 0; //如果是2则是素数,如果<2或者是>2的偶数则不是素数
for(int i=1;i<=times;i++){ //做times次随机检验
ll a=Random(n-2)+1; //得到随机检验算子 a
if(!witness(a,n))//用a检验n是否是素数
return 0;
}
return 1;
}
int main(){
ll aim;
while(cin>>aim){
if(miller_rabin(aim)) //检验tar是不是素数
cout << "Yes, Prime!" << endl;
else
cout << "No, not prime.." << endl;
}
return 0;
}
欧拉公式求有多少小于等它并与它互质的数
ll Euler(ll n){ //欧拉函数
ll ans=n,res=n;
for(ll i=2;i<=sqrt(n);i++){
if(!pri[i]){
if(res%i==0){
ans=ans/i*(i-1);
while(res%i==0)
res/=i;
}
}
}
if(res>1)
ans=ans/res*(res-1);
return ans;
}
还有一个无质数保存版本
ll Euler(ll x){
ll ans=x;
for(ll i=2;i*i<=x;i++){
if(x%i==0){
ans=ans-ans/i;
while(x%i==0)
x/=i;
}
}
if(x>1)
ans=ans-ans/x;
return ans;
}
线性求欧拉+素数
const int maxn=10000005;
int pri[maxn],num;
bool vis[maxn];
ll euler[maxn];
void getpri(){
for(int i=2;i
求1-n中每个数的欧拉函数
const int maxn=1000005;
void get_euler(){
euler[maxn];
for(int i=1;i
辗转相除法
ll exgcd(ll a,ll b,ll &x,ll &y){
if(b==0){
x=1,y=0;
return a;
}
else {
ll d=exgcd(b,a%b,y,x);
y-=x*(a/b);
return d;
}
}
高斯消元模板
double A[maxn<<1][maxn],x[maxn];//A矩阵中每一行1~n存系数,n+1为答案,m个方程m行,x是最终的答案
//注意空间要多开几个,还要考虑n,m不同的情况
int n,m;
int Guass(int n,int m){//n个未知数,m个方程
int i=1,j=1,k,r,c;
while(i<=m && j<=n){//处理第i个方程,第j个未知数
r=i;//找绝对值最大的系数,防止除数为0,并使得其他方程组系数不会太大
for(k=i+1;k<=m;k++)if(fabs(A[k][j])>fabs(A[r][j]))r=k;
if(fabs(A[r][j])>=eps){
//为0时,说明此项已被消掉,直接算下一未知数,方程不变,不过一般来说跳过的这个元素没有固定解
for(c=1;c<=n+1;c++)swap(A[i][c],A[r][c]);//交换
for(k=i+1;k<=m;k++)
if(fabs(A[k][j])>=eps){
double f=A[k][j]/A[i][j];
for(c=j;c<=n+1;c++)//当前方程j前面的系数都是0
A[k][c]-=f*A[i][c];
}
i++;//获取下一个方程
}
j++;//去消下一个未知数
}
//必须先判无解再判断多解
for(k=i;k<=m;k++)if(fabs(A[k][n+1])>=eps)return 0;//若有一行系数为0但是不为答案,则无解
if(i<=n)return 2;//如处理出的方程没有n个,则为多解。(i=n表示解决了n-1个方程)
for(int i=n;i>=1;i--){
for(j=i+1;j<=n;j++)
A[i][n+1]-=A[i][j]*x[j];
x[i]=A[i][n+1]/A[i][i];
}
//最终统计出的答案x[i]对应第i个元素,换的只是方程顺序
return 1;//拥有唯一解
}