ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

BSGS算法 || POJ2417 || luogu P3846

2022-08-05 01:31:26  阅读:192  来源: 互联网

标签:__ return P3846 luogu ll long POJ2417 res bsgs


吐了。。。写完poj2417之后意识到poj不支持stl和__int128。。。你好歹是个大学的软件,不管你们acmer的吗。。

鬼才写快速乘和hash。不让我用__int128和map我就不交poj上了。发现luogu有一模一样的板子题。

题目:P3846 [TJOI2007] 可爱的质数/【模板】BSGS

题意:

 

 

 

讲一下bsgs算法。bsgs算法的思路是,既然答案要求L,设m为sqrt(P),则可将L表示为km-j(其中0<=k,j<=m,且 km-j>=0 )。

(由费马小定理可知若存在L,L必小于P。)则原式转化为Bkm=N×Bj。原问题转化为找出该方程的一组解,并且使得L=km-j最小。

大学生(可以公然使用STL的人上人)的做法是:预处理出N×Bj(mod P)的值,并且用map记录此时的 j 值。然后从0到m枚举k,

只要满足上式且km-j>=0即可的出答案。注意bsgs不能处理余数为0的情况。

由于虽然对P取模,但是两个long long相乘仍可能炸long long,所以大部分bsgs题目需要一些处理。苦逼高中生的做法是快速乘。

快乐大学生的做法是直接用(__int128)暂时存储相乘后的结果,取模后再强制转化回long long类型。

其实可以不用快速幂,luogu上测了199ms;用了快速幂后是366ms。因为单次快速幂是log的,本来很快,但是bsgs问题P太大了。

bsgs算法时间复杂度约为O(sqrt(P))。

代码:

不使用快速幂:

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 ll p,b,n;
 5 map<ll,int>mp;
 6 /*inline ll ksm(ll a,ll b,ll p){
 7     ll res=1;
 8     while(b){
 9         if(b&1)res=(__int128)res*a%p;
10         a=(__int128)a*a%p;
11         b>>=1;
12     }
13     return res;
14 }*/
15 ll bsgs(ll p,ll b,ll n){
16     mp.clear();
17     ll m=pow(p,0.5)+1,cf=1;
18     for(int i=0;i<=m;i++){
19         if(i!=0) cf=(__int128)cf*b%p;
20         else cf=1;
21         mp[(__int128)cf*n%p]=i;
22     }
23     b=cf;
24     for(int i=0;i<=m;i++){
25         if(i) cf=(__int128)cf*b%p;else cf=1;
26         if(mp.find(cf)!=mp.end()){
27             int j=mp[cf];
28             if(i*m-j>=0) return i*m-j;
29         }
30     }
31     return -1;
32 }
33 int main(){
34     while(~scanf("%lld%lld%lld",&p,&b,&n)){
35         if(n!=0){
36             ll ans=bsgs(p,b,n);
37             if(ans!=-1) printf("%lld\n",ans);
38             else puts("no solution");
39         }
40         // bsgs 不能处理整除的情况。但是这道题不涉及。 
41     }
42     return 0;
43 }
View Code

使用快速幂:

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 ll p,b,n;
 5 map<ll,int>mp;
 6 inline ll ksm(ll a,ll b,ll p){
 7     ll res=1;
 8     while(b){
 9         if(b&1)res=(__int128)res*a%p;
10         a=(__int128)a*a%p;
11         b>>=1;
12     }
13     return res;
14 }
15 ll bsgs(ll p,ll b,ll n){
16     mp.clear();
17     ll m=pow(p,0.5)+1,cf=1;
18     for(int i=0;i<=m;i++){
19         cf=ksm(b,i,p);
20         mp[(__int128)cf*n%p]=i;
21     }
22     b=ksm(b,m,p);
23     for(int i=0;i<=m;i++){
24         cf=ksm(b,i,p);
25         if(mp.find(cf)!=mp.end()){
26             int j=mp[cf];
27             if(i*m-j>=0) return i*m-j;
28         }
29     }
30     return -1;
31 }
32 int main(){
33     while(~scanf("%lld%lld%lld",&p,&b,&n)){
34         if(n!=0){
35             ll ans=bsgs(p,b,n);
36             if(ans!=-1) printf("%lld\n",ans);
37             else puts("no solution");
38         }
39         // bsgs 不能处理整除的情况。但是这道题不涉及。 
40     }
41     return 0;
42 }
View Code

By:AlenaNuna

标签:__,return,P3846,luogu,ll,long,POJ2417,res,bsgs
来源: https://www.cnblogs.com/AlenaNuna/p/16552788.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有