登月计划
- 总时间限制:
- 40000ms
- 内存限制:
- 256000kB
- 描述
-
HJA在和学弟学数学,于是便有了一道非常简单的数学题:求满足 的最小自然数x。
- 输入
- 输入数据一行三个正整数a、b、p,我们保证p是一个质数。
- 输出
- 一行一个整数代表最小的自然数x,如果不存在这样的x输出-1。
- 样例输入
-
2 1 3
- 样例输出
-
0
- 提示
- 对于30%的数据,1≤p≤1000。
对于100%的数据,1≤a,b<p≤10^12。< dd=""> - 来源
- zhonghaoxi
BabyStepGiantStep
這道題考場上卡在了求解 a*x == b (mod p) 這一步上。
解a*x == b (mod p) 方法爲
a * b^(-1) * x == 1 (mod p)
x= (a*b^(-1))^(-1)
然而這樣還是要TLE,觀察發現其中每次求值時a總會乘上一個常數t,則x每次乘上t^(-1)就行了
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<ctime> #include<cmath> #include<algorithm> #include<set> #include<map> #include<vector> #include<string> #include<queue> using namespace std; #ifdef WIN32 #define LL "%I64d" #else #define LL "%lld" #endif #define MAXN 1100000 #define MAXV MAXN*2 #define MAXE MAXV*2 #define INF 0x3f3f3f3f #define INFL 0x3f3f3f3f3f3f3f3fLL #define VAL1 1000007 #define PROB "braveheart" typedef long long qword; qword base,res,mod; struct Edge { qword t,v; Edge *next; }E[MAXE],*V[VAL1+1]; int tope=-1; void addedge(int x,qword y,qword z) { E[++tope].t=y; E[tope].v=z; E[tope].next=V[x]; V[x]=&E[tope]; } inline qword multi(qword x,qword y) { qword ret=0; if (y<0)y=-y,x=-x; while (y) { if (y&1)ret=(ret+x)%mod; x=(x+x)%mod; y>>=1; } return ret; } qword pow_mod(qword x,qword y,qword mod) { qword ret=1; while (y) { if (y&1)ret=multi(ret,x); x=multi(x,x); y>>=1; } return ret; } int main() { freopen(PROB".in","r",stdin); freopen(PROB".out","w",stdout); int i; qword x,y,z; scanf(LL LL LL,&base,&res,&mod); int sb=ceil(sqrt(mod-1)); //baby step x=1; for (i=0;i<sb;i++) { addedge(x%VAL1,i,x); x=multi(x,base); } qword val1; val1=pow_mod(base,sb,mod); qword a_i=1; Edge *ne; bool flag=false; qword t; x=res%mod; y=pow_mod(val1,mod-2,mod); for (i=0;i<=sb;i++) { for (ne=V[x%VAL1];ne;ne=ne->next) { if (ne->v==x) { flag=true; t=ne->t; } } if (flag) { printf(LL " ",(qword)i*sb+t); return 0; } x=multi(x,y); } printf("-1 "); return 0; }