Qt系統學習第二天(資原始檔圖片新增,QDialog,QMessageBox,佈局)
阿新 • • 發佈:2022-03-10
板子題
題目傳送門
題目大意:求關於 \(x\) 的方程 \(a^x\equiv b\pmod p\) 的最小整數解,其中 \(p\) 為質數,且 \(2\le a,b<p<2^{31}\)。(這裡換了一下字母,主要是為了方便)
題目解析
因為 \(p\) 為質數,根據尤拉定理/費馬小定理可知 \(a\equiv a^{p-1}\pmod p\),也就是說,最小解肯定小於 \(p\),這樣就可以使用 BSGS 來求解。
演算法實現
B(拔)S(山)G(蓋)S(世),全稱為 baby step gaint step,翻譯為小步大步演算法,該演算法可以用來解關於 \(x\) 的方程 \(a^x\equiv b\pmod p\)
演算法思路大致如下:
令 \(t=\lceil\sqrt{p}\rceil\),對 \(x\) 模 \(t\) 討論。
設 \(x=At-B\),其中 \(0<A\le t\) 且 \(0\le B<t\)。
那麼原方程就化為 \[a^{At-B}\equiv b\pmod p \]
展開得到
\[\begin{equation} \left(a^t\right)^A\left(a^B\right)^{-1}\equiv b\pmod p \end{equation} \]其實就是
這樣我們只需要先列舉 \(B\),扔到雜湊表裡面,然後列舉 \(A\) 查詢即可。
這樣複雜度就由暴力的 \(O\left(p\right)\) 降到了 \(O\left(\sqrt{p}\right)\)。
說明:由於 \(\left(1\right)\) 式中出現了 \(a^B\) 在模 \(p\) 意義下的逆元,所以為了保證式子有意義,所以要求 \(\gcd\left(a,p\right)=1\)。
程式碼:
#include<cmath> #include<cstdio> #define db double #define gc getchar #define pc putchar #define U unsigned #define ll long long #define ld long double #define ull unsigned long long #define Tp template<typename _T> #define Me(a,b) memset(a,b,sizeof(a)) Tp _T mabs(_T a){ return a>0?a:-a; } Tp _T mmax(_T a,_T b){ return a>b?a:b; } Tp _T mmin(_T a,_T b){ return a<b?a:b; } Tp void mswap(_T &a,_T &b){ _T tmp=a; a=b; b=tmp; return; } Tp void print(_T x){ if(x<0) pc('-'),x=-x; if(x>9) print(x/10); pc((x%10)+48); return; } #define EPS (1e-7) #define INF (0x7fffffff) #define LL_INF (0x7fffffffffffffff) #define maxn 1000039 #define maxm #define MOD 1000007 #define Type long long #ifndef ONLINE_JUDGE //#define debug #endif using namespace std; Type read(){ char c=gc(); Type s=0; int flag=0; while((c<'0'||c>'9')&&c!='-') c=gc(); if(c=='-') c=gc(),flag=1; while('0'<=c&&c<='9'){ s=(s<<1)+(s<<3)+(c^48); c=gc(); } if(flag) return -s; return s; } struct JTZ{ int flag,x,s; } data[maxn]; void ins(int x,int y){ int pos=x%MOD; while(1){ if(!data[pos].flag){ data[pos].flag=1,data[pos].x=x,data[pos].s=y; return; } else if(data[pos].x==x){ data[pos].s=mmin(data[pos].s,y); return; } pos++; if(pos>=MOD) pos%=MOD; } return; } int find(int x){ int pos=x%MOD; while(1){ if(!data[pos].flag) return -1; else if(data[pos].x==x) return data[pos].s; pos++; if(pos>=MOD) pos%=MOD; } return -1; } ll fastpow(ll x,ll y,ll p){ ll res=1,tmp=x; while(y){ if(y&1) res=res*tmp%p; y>>=1; tmp=tmp*tmp%p; } return res; } ll a,b,p,sp,res,tmp,ans; int main(){ //freopen(".in","r",stdin); //freopen(".out","w",stdout); p=read(); a=read(); b=read(); sp=(ll)ceil(sqrt(p)); res=1; tmp=fastpow(a,sp,p); int i; res=1; for(i=0;i<=sp;i++) ins(b*res%p,i),res=res*a%p; res=1; tmp=fastpow(a,sp,p); for(i=1;i<=sp;i++){ res=res*tmp%p; ans=find(res); if(ans!=-1){ print(i*sp-ans); return 0; } } puts("no solution"); return 0; }