同余方程
注意:数学中的 模运算 与 计算机中的 模运算 不同
计算机中: 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;
}
之前写过一次,今天考试竟然又写错了╮(╯▽╰)╭
写篇题解来加深一下自己的印象。