题目
几乎原题 BZOJ3122题解
分析
先推一波公式,然后除去特殊情况分类讨论,剩下就是形如 $a^i equiv b(mod p)$ 的方程,可以使用BSGS算法。
在标准的BSGS中,内外层循环都是 $sqrt p$,题目查询 $m$ 次,$m leq 1000$,$ p leq 10^9$,这样总时间复杂度为 $O(m sqrt p)$,勉强能接受。据说使用读入优化和手写哈希还是能过得,可见Cls的代码%%%
仔细想一下,由于BSGS分成两步,其中第一步是建立 $a$ 的幂次方的表,而题恰好是 $a,p$相同下的一组询问,所以这一部分可以与处理。
显然,我们应该对这部分分大点,第二步就会小写(因为积一定),
如分成 $sqrt {mp} imes sqrt{frac{p}{m}}$(前面是预处理时间,后面是每次查询的时间)
也可以是 $frac{p}{1000} imes 1000$,总之,要是预处理部分大一点。
#include<bits/stdc++.h> #define rep(i,a,n) for(int i=a;i<=n;i++) #define per(i,a,n) for(int i=n;i>=a;i--) #define pb push_back #define mp make_pair #define FI first #define SE second #define maxn 100000 #define inf 0x3f3f3f3f using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> pii; typedef vector<int> vi; typedef double db; int mod; int m=1000; const int M=12000005; int hs[M],head[M],nxt[M],id[M],top; void insert(int x,int y) { int k=x%M; hs[top]=x,id[top]=y,nxt[top]=head[k],head[k]=top++; } int find(int x) { int k=x%M; for(int i=head[k];i!=-1;i=nxt[i]) if(hs[i]==x) return id[i]; return -1; } int BSGS(int a,int b,int n) { if(b==1) return 0; ll p=1; int ans=inf; rep(i,0,m) { int id=find(1ll*p*b%n); if(id!=-1) ans=min(ans,id-i); p=p*a%mod; } if(ans==inf) return -1; return ans; } ll qp(ll a,ll k) { ll res=1; while(k) { if(k&1) res=res*a%mod; a=a*a%mod; k>>=1; } return res; } ll _inv(ll x) {return qp(x,mod-2);} int main() { int CAS; scanf("%d",&CAS); while(CAS--) { ll N; int x0,a,b; scanf("%lld%d%d%d%d",&N,&x0,&a,&b,&mod); memset(head,-1,sizeof head); top=1; int bn=(mod+m-1)/m; int aA=qp(a,m),pw=aA; rep(i,1,bn) { if(find(pw)==-1) insert(pw,i*m); pw=1ll*pw*aA%mod; } int Q; scanf("%d",&Q); while(Q--) { int v; scanf("%d",&v); if(a==0) { if(v==x0) puts("0"); else if(v==b) { if(N==1) puts("-1"); else puts("1"); } else puts("-1"); } else if(a==1) { if(b==0) { if(v==x0) puts("0"); else puts("-1"); } else { ll n=1ll*(v+mod-x0)*_inv(b)%mod; if(n>=N) puts("-1"); else printf("%lld ",n); } } else { v=(1ll*(a-1)*v+b)%mod; int X=(1ll*(a-1)*x0+b)%mod; if(X==0) { if(v==0) puts("0"); else puts("-1"); } else { v=1ll*v*_inv(X)%mod; if(v==0) puts("-1"); else { int n=BSGS(a,v,mod); if(n>=N) puts("-1"); else printf("%d ",n); } } } } } return 0; }
参考链接:https://ac.nowcoder.com/acm/contest/view-submission?submissionId=41008097