洛谷 P4454 [CQOI2018]破解D-H协议
2024-09-18 18:03:26
题目
https://www.luogu.com.cn/problem/P4454
杂题乱做ing...
思路
首先我们把式子列一下:
\(g^a\equiv A(mod P)\)
\(g^b\equiv B(mod P)\)
求\(g^{ab}\)
g是原根,那是不是要用到一些高妙的数论性质呀。。。然后我们看一眼式子,发现只要把\(a\)和\(b\)求出来就行了,也就是求\(A\)和\(B\)在模\(P\)意义下的离散对数。
这不就是个BSGS裸题嘛,为什么能评成紫题啊。。。
代码(伪)
点击查看代码
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<map>
#define ll long long
using namespace std;
map<int,int> H;
ll kasumi(ll x,ll p,ll m){
ll ans=1,base=x;
for(;p;p>>=1){
if(p&1) ans=ans*base%m;
base=base*base%m;
}
return ans;
}
ll BSGS(ll a,ll b,ll p){
int i;
H.clear();
ll k=(ll)(sqrt(p)+1);
ll ak=1;
H[b]=0;
for(i=1;i<k;++i){
ak=ak*a%p;
H[(int)(ak*b%p)]=i;
}
ak=ak*a%p;
ll t=1;
for(i=1;i<=k;++i){
t=t*ak%p;
if(H.count((int)t)){
int z=H.find((int)t)->second;
return i*k-z;
}
}
}
int main(){
int T;
ll g,P;
ll a,b,A,B;
ll ans;
scanf("%lld%lld",&g,&P);
scanf("%d",&T);
while(T--){
scanf("%lld%lld",&A,&B);
a=BSGS(g,A,P);
b=BSGS(g,B,P);
ans=kasumi(g,a*b%(P-1),P);
printf("%lld\n",ans);
}
// system("pause");
return 0;
}
喜闻乐见卡map,然后我们自己写个哈希表,这题就水完了。
代码(真)
点击查看代码
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#define ll long long
#define zzd 233333
using namespace std;
struct Hashmap{
int fst[zzd],nxt[1<<16],cnt;
struct data{
int x,y;
} d[1<<16];
void clear(){
cnt=0;
memset(fst,0,sizeof(fst));
memset(nxt,0,sizeof(nxt));
}
int insert(int t1,int t2){
d[++cnt].x=t1;
d[cnt].y=t2;
nxt[cnt]=fst[t1%zzd];
fst[t1%zzd]=cnt;
}
int find(int t){
int i=fst[t%zzd];
while(i&&d[i].x!=t) i=nxt[i];
if(i) return d[i].y;
else return -1;
}
} H;
ll kasumi(ll x,ll p,ll m){
ll ans=1,base=x;
for(;p;p>>=1){
if(p&1) ans=ans*base%m;
base=base*base%m;
}
return ans;
}
ll BSGS(ll a,ll b,ll p){
int i;
H.clear();
ll k=(ll)(sqrt(p)+1);
ll ak=1;
H.insert(b,0);
for(i=1;i<k;++i){
ak=ak*a%p;
H.insert((int)(ak*b%p),i);
}
ak=ak*a%p;
ll t=1;
for(i=1;i<=k;++i){
t=t*ak%p;
int z=H.find((int)t);
if(z>=0) return i*k-z;
}
}
int main(){
int T;
ll g,P;
ll a,b,A,B;
ll ans;
scanf("%lld%lld",&g,&P);
scanf("%d",&T);
while(T--){
scanf("%lld%lld",&A,&B);
a=BSGS(g,A,P);
b=BSGS(g,B,P);
ans=kasumi(g,a*b%(P-1),P);
printf("%lld\n",ans);
}
// system("pause");
return 0;
}
最新文章
- 修改安卓串口蓝牙app问题记录
- bash获取properties文件资源
- matlab 按照某列以行为单位进行排序
- (1)Underscore.js入门
- hibernate 一对一关联关系 及其懒加载,总结
- Swift学习--常量.变量.数据类型的使用(二)
- oracle PL/SQL(procedure language/SQL)程序设计(在PL/SQL中使用SQL)
- js字符串长度计算(一个汉字==两个字符)和字符串截取
- 统计难题 HDOJ--2222
- Oracle数据库之动态SQL
- HDOJ3374 String Problem 【KMP】+【最小表示法】
- 只获取linux ip的命令
- java结构与算法之冒泡排序
- 安装aptana(1)
- Android开发系列之adb常用命令
- awk命令的基本使用
- Eclipse安装ModelGoon控件(ModelGoon控件反向生成UML)
- 20155210 Exp7 网络欺诈防范
- 创建 HelloWorld 项目
- Easyui layout设置满屏效果