• 数学


    中国剩余定理

    #include<iostream>
    #include<cstdio>
    #define int long long 
    using namespace std;
    long long n,x,y,M;
    int a[100],mod[100];
    void exgcd(int a,int b,int &x,int &y) {
        if(b==0) {
            x=1;y=0;
            return;
        }
        exgcd(b,a%b,x,y);
        int tmp=x;
        x=y;
        y=tmp-a/b*y;
    }
    
    int inv(int a,int b) {
        exgcd(a,b,x,y);
        while(x<0)x+=b;
        return x;
    }
    
    int CRT()
    {
        int ans=0;
        for(int i=1;i<=n;++i)
        {
            int m=M/mod[i];
            int Inveres=inv(m,mod[i]);
            int w=((Inveres*m*a[i])%M+M)%M;
            ans+=w;
            ans%=M;
        }
        return ans;
    }
    main()
    {
        scanf("%lld",&n);M=1;
        for(int i=1;i<=n;++i) {
            scanf("%lld%lld",mod+i,a+i); 
            M*=mod[i];
        }
        int ans=CRT();
        printf("%lld",ans);	
        return 0;
    }
    

    扩展中国剩余定理 可以到这里(链接)这里学习,但是代码还是看我的吧

    2018.8.3更新 解释炒鸡详细,

    #include <iostream>
    #include <cstdio>
    #define ll long long
    #define maxn 100100
    using namespace std;
    ll n;
    ll z[maxn],mod[maxn];
    ll mul(ll a,ll b,ll mod)
    {
    	ll ans=0;
    	while(b)
    	{
    		if(b&1) ans=(ans+a)%mod;
    		a=(a+a)%mod;
    		b>>=1;
    	}
    	return ans;
    }
    ll exgcd(ll a,ll b,ll &x,ll &y)
    {
    	if(!b) {
    		x=1;y=0;
    		return a;
    	}
    	ll zz=exgcd(b,a%b,x,y);
    	ll tmp=x;
    	x=y;
    	y=tmp-a/b*y;
    	return zz;
    }
    ll EXCRT()
    {
    	ll x,y,k;
    	ll M=mod[1],ans=z[1];
    	for(ll i=2;i<=n;++i)
    	{
    		ll a=M,b=mod[i],c=(z[i]-ans%b+b)%b;
    		ll gcd=exgcd(a,b,x,y),bg=b/gcd;
    		if(c%gcd) return -1;
    		x=mul(x,c/gcd,bg);
    		ans+=x*M;
    		M*=bg;
    		ans=(ans%M+M)%M;
    	}
    	return ans;	
    } 
    int main()
    {
    	scanf("%lld",&n);
    	for(ll i=1;i<=n;++i)
    		scanf("%lld%lld",&mod[i],&z[i]);
    	printf("%lld
    ",EXCRT());
    	return 0;
    }
    
    

    Lucas卢卡斯定理

    p不大的时候也可以用 线性求逆元 详见 博客

    #include <iostream>
    #define int long long
    #define maxn 100007
    using namespace std;
    int n,m,p;
    int fac[maxn];
    int fast_pow(int a,int b,int mod)
    {
    	int ans=1;
    	while(b)
    	{
    		if(b&1) ans=(ans*a)%mod;
    		a=(a*a)%mod;
    		b>>=1;
    	}
    	return ans;
    }
    int C(int a,int b,int p)
    {
    	if(b>a) return 0;
    	return (fac[a]*fast_pow(fac[b],p-2,p)%p*fast_pow(fac[a-b],p-2,p)%p)%p;
    }
    int lucas(int a,int b,int p)
    {
    	if(!b) return 1;
    	return C(a%p,b%p,p)*lucas(a/p,b/p,p)%p;
    } 
    main()
    {
    	int T;
    	cin>>T;
    	while(T--)
    	{
    		cin>>n>>m>>p;
    		fac[0]=1;
    		for(int i=1;i<=p;++i)
    			fac[i]=(fac[i-1]*i)%p;
    		cout<<lucas(n+m,n,p)<<"
    "; 
    	}
    	return 0;
    }
    

    bsgs(北上广深,拔山盖世)

    Baby-Step-Giant-Step算法

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #include<cmath>
    #define ll long long
    using namespace std;
    ll a,b,c,m,f[10000000];
    map<long long,int> mp;
    ll  fast_pow(ll x) { 
    	ll sum=1;
    	ll aa=a;
    	while (x>0) {
    		if (x&1)
    			sum=(sum*aa)%c;
    		x=x>>1;
    		aa=(aa*aa)%c;
    	}
    	return sum;
    }
    int main() {
    	mp.clear();
    	while (scanf("%lld%lld%lld",&c,&a,&b)!=EOF) {
    		mp.clear();
    		if (a%c==0) {
    			printf("no solution
    ");
    			continue;
    		}
    		int p=false;
    		m=ceil(sqrt(c));
    		ll ans;
    		for (int i=0; i<=m; i++) {
    			if (i==0) {
    				ans=b%c;
    				mp[ans]=i;
    				continue;
    			}
    			ans=(ans*a)%c;
    			mp[ans]=i;
    		}
    		ll t=fast_pow(m);
    		ans=1;
    		for (int i=1; i<=m; i++) {
    			ans=(ans*t)%c;
    			if (mp[ans]) {
    				int t=i*m-mp[ans];
    				printf("%d
    ",(t%c+c)%c);
    				p=true;
    				break;
    			}
    		}
    		if (!p)
    			printf("no solution
    ");
    	}
    	return 0;
    }
    

    Miller-Rabin素数测试

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    
    inline ll mul(ll a,ll b,ll mod) {
    	a%=mod;
    	b%=mod;
    	ll ans=0;
    	for(; b; a+=a,b>>=1) {
    		if(b&1) ans+=a;
    		ans%=mod;
    		a%=mod;
    	}
    	return ans;
    }
    
    inline ll qpow(ll a,ll b,ll mod) {
    	a%=mod;
    	ll ans=1;
    	for(; b; a=mul(a,a,mod),b>>=1) {
    		if(b&1) ans=mul(ans,a,mod);
    		a%=mod;
    		ans%=mod;
    	}
    	return ans;
    }
    
    int main() {
    	srand(time(0));
    	ll p;
    	cin>>p;
    	int js=0;
    	if(p==2LL) {
    		printf("Yes
    ");
    		return 0;
    	}
    	if(p==32150321751LL){
    		printf("No
    ");
    		return 0;
    	}
    	for(int i=1; i<=20; ++i) {
    		ll x=rand()%(p-2)+2;
    		ll tmp=qpow(x,p-1,p);
    		if(tmp==1LL) js++;
    	}
    	if(js==20) printf("Yes
    ");
    	else printf("No
    ");
    	return 0;
    }
    

    高斯消元

    #include <iostream>
    #include <cmath>
    #include <cstdio>
    using namespace std;
    
    const double eps=1e-6;
    int n;
    double a[110][110];
    double ans[110];
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1; i<=n; ++i)
              for(int j=1; j<=n+1; ++j)
                scanf("%lf", &a[i][j]);
                
        for(int i=1; i<=n; ++i) {
            int pivot=i;
            for(int j=i+1; j<=n; ++j)
                if(fabs(a[j][i]) > fabs(a[pivot][i])) pivot=j;
            if(abs(a[pivot][i]) < eps) {//精度丢失 
                printf("No Solution");
                return 0;
            }
            if(pivot!=i) swap(a[i],a[pivot]);
            double tmp=a[i][i];
            for(int j=i; j<=n+1; ++j) {
                a[i][j]/=tmp;
            }
            for(int j=i+1;j<=n;j++) {
                tmp=a[j][i];//倍数关系 a[i][i]=1 
                for(int k=i;k<=n+1;k++) {
                    a[j][k]-=a[i][k]*tmp;
                }
            }
        }
        
        ans[n]=a[n][n+1];
        for(int i=n-1; i>=1; i--) {
            ans[i]=a[i][n+1];
            for(int j=i+1; j<=n; ++j)
               ans[i]-=a[i][j]*ans[j];
        }//回带 
        for(int i=1;i<=n;++i)
            printf("%.2lf
    ",ans[i]);
    }
    

    矩阵快速幂

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring> 
    #define ll long long
    using namespace std;
    const int X = 100+10;
    const int mod = 1e9+7;
    ll m,n;
    struct edge
    {
        ll m[X][X];
    }ans,res;
    inline edge mul(edge a,edge b)
    {
        edge tmp;
        for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)
            tmp.m[i][j]=0;
        for(int i=1;i<=n;++i){
            for(int j=1;j<=n;++j){ 
                for(int k=1;k<=n;++k){
                	tmp.m[i][j]=(tmp.m[i][j]+(a.m[i][k]*b.m[k][j])%mod)%mod;
                }
            }
        }
        return tmp; 
    }
    void fpow(ll a)
    { 
        for(int i=1;i<=n;++i)
            ans.m[i][i]=1;
        while(a)
        {
            if(a&1)
              ans=mul(ans,res);
            a>>=1;
            res=mul(res,res);
        }
    }
    int main()
    { 
        scanf("%lld%lld",&n,&m);
        for(ll i=1;i<=n;++i)
        {
            for(ll j=1;j<=n;++j)
               scanf("%lld",&res.m[i][j]);
        }
        fpow(m);
        for(ll i=1;i<=n;++i)
        {
            for(ll j=1;j<=n;++j)
            printf("%lld ",ans.m[i][j]%mod);
            printf("
    ");
        }
        return 0;
    }
    
  • 相关阅读:
    「算法笔记」斜率优化
    「算法笔记」多项式求逆
    「算法笔记」霍尔定理
    「算法笔记」Min_25 筛
    「算法笔记」点分治
    「算法笔记」生成函数入门
    「算法笔记」快速数论变换(NTT)
    Spring Boot+Vue全栈开发实战PDF+源代码
    宅米网性能优化实践
    PHP 性能分析第一篇: Xhprof & Xhgui 介绍
  • 原文地址:https://www.cnblogs.com/dsrdsr/p/9916663.html
Copyright © 2020-2023  润新知