UVA10225题解

题意简述

给定三个正整数 ABM,其中 AM 互质,求最小的正整数 L 满足:ALB(modM)

题目分析

这个题是高次同余方程的模板题。对于高次同余方程问题,一个经典的算法就是 Baby Step,Giant Step 算法,简称 BSGS 算法。以下为其具体过程:

首先设 L=x×My ,其中 0yM,那么就有 Ax×MyB(modM),又可以转化为 (AM)xB×Ay(modM)。接下来,对所有 y[0,M],将其对应的 B×Ay 插入到一个哈希表中,然后枚举 x[0,M] 的取值,计算出 (AM)x 并查找在哈希表中有无与其对应的 y 即可,最终答案就是 L=x×My,若在哈希表中没有对应的 y 的值,那么无解。

至于该算法的时间复杂度,别的题解中没有进行详细解释,此处解释一下。由于 AM 互质,所以对于任意的正整数 i,有AiAimodM(modM)。因此,若原方程有解,就有 0LM,即0x×MyM。而0yM,从而有 0xM。因此我们枚举 x 取值的时间复杂度为 O(M),同样地,建立 B×Ay 的哈希表的时间复杂度也为 O(M)。而其中计算 (AM)xAy 使得最终的时间复杂度需要乘上一个 logM,因此总时间复杂度为 O(MlogM)。另外,在代码中,我使用了 STL 的 unordered_map 代替了手写的哈希表,因为这样非常方便 (其实是我懒得自己写了),不过常数较大,在数据较大时不建议使用,并且还容易 MLE。

最后附上代码:

#include<bits/stdc++.h>
using namespace std;
int a,b,m;
int pw(int a,int b,int m)//快速幂。
{
int res=1;
for(;b;b>>=1)
{
if(b&1)
res=(long long)res*a%m;
a=(long long)a*a%m;
}
return res;
}
int BSGS(int a,int b,int m)
{
unordered_map<int,int>hash;//哈希表。
hash.clear();
a%=m;
b%=m;
int t=(int)sqrt(m)+1;
for(int i=0;i<t;i++)//枚举B乘A的y次方,建立哈希表。
{
int val=(long long)b*pw(a,i,m)%m;
hash[val]=i;
}
a=pw(a,t,m);//计算A的根号M次方,不需要每次计算一遍。
for(int i=0;i<=t;i++)//枚举A的根号M次方的x次方,并在哈希表中查找对应的y。
{
int val=pw(a,i,m);
int j=hash.find(val)==hash.end()?-1:hash[val];
if(j>=0&&i*t-j>=0)
return i*t-j;
}
return -1;//无解
}
int main()
{
while(scanf("%d%d%d",&m,&a,&b)==3)
{
if(b==1)
{
printf("0\n");
continue;
}
int ans=BSGS(a,b,m);
if(ans>=0)
printf("%d\n",ans);
else
printf("no solution\n");
}
return 0;
}

本篇是本人的第二篇题解,希望审核大大可以给过

posted @   Hadtsti  阅读(3)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示