zoukankan      html  css  js  c++  java
  • BSGS算法

    BSGS算法

    前言

    (BabyStepGiantStep)算法

    北上广深算法,orz

    算法用于解决高次同余问题,(a^xequiv b(mod c)) 满足 (gcd(a,c) = 1)

    推理过程

    根据费马小定理可知

    如果 (a)(c) 互质,满足 (a^{c-1}equiv 1(mod c)),

    自此之后 (a^{c}equiv a(mod c))

    这是一个循环过程,最小项维护在区间 ([0,c)) ,不能暴力求解,

    有一种方法 假设 (k = ceil(sqrt(c))) ,使得 (x=k×kx-ky) ,其中 (kx epsilon [1,m],ky epsilon (0,m])

    之后不断枚举 (ky) ,使用 (kx) 进行匹配就是结果。

    例题

    题目:洛谷 P4884

    点我,快点我

    题解:将 (N)(1) ,逐步分开成 (10^0 + 10^1+...+10^{N-1}), 这是一个等比数列,

    进一步化简得到 (10^n equiv (9*k+1) (mod m)) ,将公式代进去,输出结果即可。

    #include <map>
    #include <cmath>
    #include <cstdio>
    #include <iostream>
    using namespace std;
    typedef long long ll;
    ll multi(ll a,ll b,ll mod){
    	ll ret=0;
    	while(b>0){
    		if(b&1)ret=(ret+a)%mod;
    		b>>=1;
    		a=(a+a)%mod;
    	}
    	return ret;
    }
    ll pow(ll a,ll b,ll mod){
    	ll ret=1;
    	while(b>0){
    		if(b&1)ret=multi(ret,a,mod);
    		b>>=1;
    		a=multi(a,a,mod);
    	}
    	return ret;
    }
    ll BSGS(ll a,ll b,ll m){
    	ll k=ceil(sqrt(m));
    	map<ll,ll>M;
    	for(int i=0;i<=k;++i){
    		M[b]=i;
    		b=multi(b,a,m);
    	}
    	a=pow(a,k,m);
    	ll ret=a;
    	for(int i=1;i<=k;++i){
    		if(M.count(ret)){
    			return i*k-M[ret];
    		}
    		ret=multi(ret,a,m);
    	}
    	return 0;
    }
    int main(){
    	ll K,m;
    	cin>>K>>m;
    	K=(K*9+1)%m;
    	cout<<BSGS(10,K,m)<<endl;
    	return 0;
    }
    
    
    新赛季的开始
  • 相关阅读:
    poj 1269(两条直线交点)
    poj 2398(叉积判断点在线段的哪一侧)
    poj 2318(叉积判断点在线段的哪一侧)
    HDU 5650 so easy
    POJ 1328 Radar Installation
    POJ 1017 Packets
    POJ 3190 Stall Reservations
    CodeForces 652A Gabriel and Caterpillar
    CodeForces 652B z-sort
    CodeForces 652C Foe Pairs
  • 原文地址:https://www.cnblogs.com/VagrantAC/p/12499356.html
Copyright © 2011-2022 走看看