BSGS:同余方程


注意:数学中的 模运算 与 计算机中的 模运算 不同
计算机中: a%b = abs(a)%abs(b)(符号与a相同,与b无关)
数学中:都是正 (应该就是求余运算)


求最小正整数x满足:
a*x%b=1;(易得 x∈[1,b-1])
x=Block*i+j;(令Block=10000(根据题目数据大小而定))(j∈[0,Blcok-1])
a*(Blcok*i+j)%b=1;
(a*Block*i%b+a*j%b)%b=1;
!注意!

∵a>0,j>=0

∴a*j%b>=0 


->a*j%b=1-a*Block*i%b(如果1-a*Block*i%b>=0)或 a*j%b=1+b-a*Block*i%b(a-a*Block*i%b<0);
1.预处理出a*j%b (mp[a*j%b]=j)
(如果a*j%b==1 则当i=0时就是所求的最小正整数x 即结果就是 j)
2.for(int i=0;i<=2e9/Blcok;i++) 即可得到 1-a*Block*i%b 和 1+b-a*Block*i%b
(是从0开始,而不是1,否则小于Block的值都没有考虑到)
3.再映射,看有没有对应的a*j%b存在
(若存在则答案就是 x = Block*i+j = Block*i +
mp[ 1-a*Block*i%b ] (1-a*Block*i%b>=0) 或 mp[1+b-a*Block*i%b] (1-a*Block*i%b<0))

代码如下:

#include<map>
#include<cstdio>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
map<ll,int>mp;
int main(){
    int a,b;
    cin>>a>>b;
    int Block=10000;
    for(int j=0;j<Block;j++){
        ll pre=1LL*a*j%b;
        //如果在之前已经有过这个值了那么就以之前的值为准,因为之前的值小一点(所求的是最小正整数解) 
        if(mp.find(pre)!=mp.end())continue;
        if(pre==1){
            cout<<j<<endl;
            return 0;
        }
        mp[pre]=j;
    }
    for(int i=0;i*Block<=b;i++){//x∈[1,b-1]
        ll pre=1LL-1LL*a*Block*i%b;
        if(pre<0)pre+=1LL*b;
        if(mp.find(pre)!=mp.end()){
            ll x=1LL*Block*i+1LL*mp[pre];
            cout<<x<<endl;
        }
    }
    return 0;
}

之前写过一次,今天考试竟然又写错了╮(╯▽╰)╭
写篇题解来加深一下自己的印象。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值