我们要对算法进行一些修改,使得其可以进行上述的处理。具体证明去看AekdyCoin犇的题解,我就是简单讲一下我的理解。
一开始的方程等价于A^x+C*b=B(a,b是整数),现在gcd(A,C)!=1,不妨令t=gcd(A,C)
我们考虑方程(A/t)A^x’%(C/t)=(B/t)的解x’与原来的解x有什么关系。
显然现在的方程等价于(A/t)A^x’+(C/t)*b’=B/t.
两端均乘以t得到:A^(x’+1)+C*b’=B
由系数相等有:x=x’+1,b=b’.
那么我们就有一种方法算出x了。先算出x’,再加上1就行了。
考虑如何求出x’,现在的方程如果A,C依旧不互质,就继续迭代将系数除以最大公约数,同时前面的常数增大。
然后求出解之后再加上总共除的次数就好了。
#include<cstdio> #include<cstdlib> #include<algorithm> #include<map> #include<cmath> using namespace std; typedef long long ll; ll A,B,P; inline ll Pow(ll a,ll b) { if (!b) return 1LL; ll ret=Pow(a,b>>1); if (b&1) return ret*ret%P*a%P; return ret*ret%P; } map<ll,int> M; inline void solve() { M.clear(); A%=P; if (!A && !B) { printf("1\n"); return; } if (!A) { printf("no solution\n"); return; } ll m=ceil(sqrt((double)P)),tmp=1; M[1]=m+1; for (int i=1;i<m;i++) { (tmp*=A)%=P; if (!M[tmp]) M[tmp]=i; } ll inv=1,T=Pow(A,P-1-m); for (int k=0;k<m;k++) { int i=M[B*inv%P]; if (i) { if (i==m+1) i=0; printf("%lld\n",k*m+i); return; } (inv*=T)%=P; } printf("no solution\n"); } int main() { freopen("t.in","r",stdin); freopen("t.out","w",stdout); while (~scanf("%lld%lld%lld",&P,&A,&B)) solve(); return 0; }
#include<cstdio> #include<cstdlib> #include<algorithm> #include<map> #include<cmath> using namespace std; typedef long long ll; inline char nc() { static char buf[100000],*p1=buf,*p2=buf; if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; } return *p1++; } inline void read(ll &x) { char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } inline void write(ll x,char c) { if (x==0) { putchar('0'); putchar(c); return; } if (x<0) putchar('-'),x=-x; char s[55]={0},len=0; while (x) s[++len]=x%10+'0',x/=10; for (int i=len;i;i--) putchar(s[i]); putchar(c); } namespace Work1{ ll A,B,P; inline ll Pow(ll a,ll b) { if (!b) return 1LL; ll ret=Pow(a,b>>1); if (b&1) return ret*ret%P*a%P; return ret*ret%P; } inline void work() { read(A); read(B); read(P); write(Pow(A,B),'\n'); } } namespace Work2{ #define X first #define Y second typedef pair<ll,ll> data; ll A,B,P; ll D; inline data EXGCD(ll a,ll b) { if (!b) { D=a; return data(1,0); } data ret=EXGCD(b,a%b); return data(ret.Y,ret.X-a/b*ret.Y); } inline void solve() { data ret=EXGCD(A,P); if (B%D==0) { ll ans=((ret.X*B/D)%P+P)%P; write(ans,'\n'); } else printf("Orz, I cannot find x!\n"); } inline void work() { read(A); read(B); read(P); solve(); } } namespace Work3{ ll A,B,P; inline ll Pow(ll a,ll b) { if (!b) return 1LL; ll ret=Pow(a,b>>1); if (b&1) return ret*ret%P*a%P; return ret*ret%P; } map<ll,int> M; inline void solve() { M.clear(); A%=P; if (!A && !B) { printf("1\n"); return; } if (!A) { printf("Orz, I cannot find x!\n"); return; } ll m=ceil(sqrt((double)P)),tmp=1; M[1]=m+1; for (int i=1;i<m;i++) { (tmp*=A)%=P; if (!M[tmp]) M[tmp]=i; } ll inv=1,T=Pow(A,P-1-m); for (int k=0;k<m;k++) { int i=M[B*inv%P]; if (i) { if (i==m+1) i=0; write(k*m+i,'\n'); return; } (inv*=T)%=P; } printf("Orz, I cannot find x!\n"); } inline void work() { read(A); read(B); read(P); solve(); } } ll Q,K; int main() { freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(Q); read(K); while (Q--) { if (K==1) Work1::work(); else if (K==2) Work2::work(); else if (K==3) Work3::work(); } return 0; }
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<map> using namespace std; typedef long long ll; inline char nc() { static char buf[100000],*p1=buf,*p2=buf; if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; } return *p1++; } inline void read(ll &x) { char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } inline void write(ll x,char c) { if (x==0) { putchar('0'); putchar(c); return; } if (x<0) putchar('-'),x=-x; char s[55]={0},len=0; while (x) s[++len]=x%10+'0',x/=10; for (int i=len;i;i--) putchar(s[i]); putchar(c); } namespace MOD{ #define X first #define Y second typedef pair<ll,ll> data; ll D; inline data EXGCD(ll a,ll b) { if (a<b) { data ret=EXGCD(b,a); return data(ret.Y,ret.X); } if (!b) { D=a; return data(1,0); } data ret=EXGCD(b,a%b); return data(ret.Y,ret.X-a/b*ret.Y); } inline ll Inv(ll A,ll P) { data ret=EXGCD(A,P); return (ret.X%P+P)%P; } inline ll Solve(ll A,ll B,ll P) { data ret=EXGCD(A,P); if (B%D==0) { ll ans=((ret.X*B/D)%P+P)%P; return ans; } else return -1; } } namespace BSGS{ inline ll Pow(ll a,ll b,ll p) { ll ret=1; for (;b;b>>=1,a=a*a%p) if (b&1) (ret*=a)%=p; return ret; } map<ll,int> M; inline ll Solve(ll A,ll B,ll P) { M.clear(); A%=P; if (!A && !B) return 1LL; if (!A) return -1; ll m=sqrt((double)P)+1,tmp=1; M[1]=m+1; for (int i=1;i<m;i++) { (tmp*=A)%=P; if (!M[tmp]) M[tmp]=i; } ll inv=1,T=Pow(A,P-1-m,P); for (int k=0;k<m;k++) { int i=M[B*inv%P]; if (i) { if (i==m+1) i=0; return k*m+i; } (inv*=T)%=P; } return -1; } } ll P,A,B,X,T; ll N; int main() { ll Q; freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(Q); while (Q--) { read(P); read(A); read(B); read(X); read(T); if (X==T) { printf("1\n"); continue; } if (A==0) { if (B==T) { printf("2\n"); continue; } else { printf("-1\n"); continue; } } if (A==1) { N=MOD::Solve(B,((T-X+B)%P+P)%P,P); if (N==0) N=P; } else { ll C=MOD::Inv(A-1,P); ll AN=MOD::Solve((X+B*C)%P,(B*C+T)%P,P); if (AN==-1) N=-1; else { N=BSGS::Solve(A,AN,P); if (N!=-1) N++; } } write(N,'\n'); } return 0; }
#include<cstdio> #include<cstdlib> #include<cmath> #include<map> #include<algorithm> #include<cstring> using namespace std; typedef long long ll; inline char nc() { static char buf[100000],*p1=buf,*p2=buf; if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; } return *p1++; } inline void read(ll &x) { char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } inline void write(ll x,char c) { if (x==0) { putchar('0'); putchar(c); return; } if (x<0) putchar('-'),x=-x; char s[55]={0},len=0; while (x) s[++len]=x%10+'0',x/=10; for (int i=len;i;i--) putchar(s[i]); putchar(c); } #define mod 1313131 struct Hashset { int head[mod], next[35010], f[35010], v[35010], ind; void reset() { ind = 0; memset(head, -1, sizeof head); } void insert(int x, int _v) { int ins = x % mod; for(int j = head[ins]; j != -1; j = next[j]) if (f[j] == x) { v[j] = min(v[j], _v); return; } f[ind] = x, v[ind] = _v; next[ind] = head[ins], head[ins] = ind++; } int operator [] (const int &x) const { int ins = x % mod; for(int j = head[ins]; j != -1; j = next[j]) if (f[j] == x) return v[j]; return -1; } }M; #define X first #define Y second typedef pair<ll,ll> data; inline data EXGCD(ll a,ll b) { if (a<b) { data ret=EXGCD(b,a); return data(ret.Y,ret.X); } if (!b) { return data(1,0); } data ret=EXGCD(b,a%b); return data(ret.Y,ret.X-a/b*ret.Y); } inline ll Inv(ll A,ll P) { data ret=EXGCD(A,P); return (ret.X%P+P)%P; } inline ll Pow(ll a,ll b,ll p) { ll ret=1; for (;b;b>>=1,a=a*a%p) if (b&1) (ret*=a)%=p; return ret; } //map<ll,int> M; inline ll BSGS(ll A,ll B,ll P) { // M.clear(); M.reset(); A%=P; if (!A && !B) return 1LL; if (!A) return -1; ll m=sqrt((double)P)+1,tmp=1; M.insert(1,m+1); for (int i=1;i<m;i++) { (tmp*=A)%=P; if (M[tmp]==-1) M.insert(tmp,i); } ll inv=1,T=Inv(Pow(A,m,P),P); for (int k=0;k<m;k++) { int i=M[B*inv%P]; if (i!=-1) { if (i==m+1) i=0; return k*m+i; } (inv*=T)%=P; } return -1; } ll A,B,P,ans; inline ll Calc(ll A,ll B,ll P) { ll tmp=1; for (int i=0;i<100;(tmp*=A)%=P,i++) if (tmp==B) return i; ll C=1,D,num=0,ret; data G; while (1) { G=EXGCD(A,P); D=A*G.first+P*G.second; if (D==1) { (B*=Inv(C,P))%=P; ret=BSGS(A,B,P); if (ret==-1) return -1; return ret+num; } if (B%D) return -1; B/=D; P/=D; (C*=A/D)%=P; num++; } } int main() { freopen("t.in","r",stdin); freopen("t.out","w",stdout); while (1) { read(A); read(P); read(B); if (!A && !B && !P) break; ans=Calc(A,B,P); if (ans==-1) printf("No Solution\n"); else write(ans,'\n'); } return 0; }
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<map> #include<cstring> #define cl(x) memset(x,0,sizeof(x)) using namespace std; typedef long long ll; inline char nc() { static char buf[100000],*p1=buf,*p2=buf; if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; } return *p1++; } inline void read(ll &x) { char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } inline void write(ll x,char c) { if (x==0) { putchar('0'); putchar(c); return; } if (x<0) putchar('-'),x=-x; char s[55]={0},len=0; while (x) s[++len]=x%10+'0',x/=10; for (int i=len;i;i--) putchar(s[i]); putchar(c); } inline ll Mul(ll A,ll B,ll P) { A%=P,B%=P; ll ret=A*B-(ll)((double)A/P*B+0.5)*P; return ret<0?ret+P:ret; } inline ll Pow(ll A,ll B,ll P) { ll ret=1; for (;B;B>>=1,A=Mul(A,A,P)) if (B&1) ret=Mul(ret,A,P); return ret; } #define X first #define Y second typedef pair<ll,ll> data; inline data EXGCD(ll a,ll b) { if (a<b) { data ret=EXGCD(b,a); return data(ret.Y,ret.X); } if (!b) { return data(1,0); } data ret=EXGCD(b,a%b); return data(ret.Y,ret.X-a/b*ret.Y); } inline ll Inv(ll A,ll P) { data ret=EXGCD(A,P); return (ret.X%P+P)%P; } namespace Work1{ ll A,B,P; inline void Solve() { read(A); read(B); read(P); write(Pow(A,B,P),'\n'); } } namespace Work2{ #define mod 1313131 struct Hashset { int head[mod], next[35010], f[35010], v[35010], ind; void reset() { ind = 0; memset(head, -1, sizeof head); } void insert(int x, int _v) { int ins = x % mod; for(int j = head[ins]; j != -1; j = next[j]) if (f[j] == x) { v[j] = min(v[j], _v); return; } f[ind] = x, v[ind] = _v; next[ind] = head[ins], head[ins] = ind++; } int operator [] (const int &x) const { int ins = x % mod; for(int j = head[ins]; j != -1; j = next[j]) if (f[j] == x) return v[j]; return -1; } }M; inline ll BSGS(ll A,ll B,ll P) { M.reset(); A%=P; if (!A && !B) return 1LL; if (!A) return -1; ll m=sqrt((double)P)+1,tmp=1; M.insert(1,0); for (int i=1;i<m;i++) { (tmp*=A)%=P; if (M[tmp]==-1) M.insert(tmp,i); } ll inv=1,T=Inv(Pow(A,m,P),P); for (int k=0;k<m;k++) { int i=M[B*inv%P]; if (i!=-1) return k*m+i; (inv*=T)%=P; } return -1; } ll A,B,P,ans; inline ll Calc(ll A,ll B,ll P) { for (ll tmp=1,i=0;i<100;(tmp*=A)%=P,i++) if (tmp==B) return i; ll C=1,D,num=0,ret; data G; while (1) { G=EXGCD(A,P); D=A*G.first+P*G.second; if (D==1) { (B*=Inv(C,P))%=P; ret=BSGS(A,B,P); if (ret==-1) return -1; return ret+num; } if (B%D) return -1; B/=D; P/=D; (C*=A/D)%=P; num++; } } inline void Solve() { read(A); read(B); read(P); ans=Calc(A,B,P); if (ans==-1) printf("Math Error\n"); else write(ans,'\n'); } } namespace Work3{ namespace China{ ll A[100005],N[100005],M[100005]; int tot=0; ll P=1; inline void clear(){ P=1; tot=0; } inline void add(ll a,ll n){ A[++tot]=a; N[tot]=n; P*=n; } inline ll Solve(){ ll ret=0,inv; for (int i=1;i<=tot;i++) { M[i]=P/N[i]; inv=Inv(M[i],N[i]); (ret+=Mul(A[i],Mul(M[i],inv,P),P))%=P; } return ret; } } int vst[100005],prime[100005],num; inline void Pre() { const int maxn=100000; for (int i=2; i<=maxn; i++) if (!vst[i]) { prime[++num]=i; for (int j=i+i; j<=maxn; j+=i) vst[j]=1; } } ll M,ans; ll p[50005],a[50005],p_a[50005],cnt; ll n,m; inline void Machine(ll M) { for (int i=1; i<=num; i++) if (M%prime[i]==0) { p[++cnt]=prime[i]; while (M%prime[i]==0) a[cnt]++,M/=prime[i]; p_a[cnt]=Pow(p[cnt],a[cnt],1000000); } } inline data Calc(ll x,ll p,ll a,ll p_a) { ll A=1,B=1; for (ll i=1;i<p_a;i++) if (i%p) (A*=i)%=p_a; A=Pow(A,x/p_a,p_a); for (ll i=x-x%p_a+1;i<=x;i++) if (i%p) (A*=i)%=p_a; B=x/p; if (B) { data tmp=Calc(B,p,a,p_a); (A*=tmp.first)%=p_a; B+=tmp.second; } return data(A,B); } inline void Solve() { China::clear(); cnt=0; cl(p); cl(a); cl(p_a); data ret,tmp; read(m); read(n); read(M); Machine(M); for (int i=1;i<=cnt;i++) { ret=Calc(n,p[i],a[i],p_a[i]); tmp=Calc(m,p[i],a[i],p_a[i]); ret.second-=tmp.second; (ret.first*=Inv(tmp.first,p_a[i]))%=p_a[i]; tmp=Calc(n-m,p[i],a[i],p_a[i]); ret.second-=tmp.second; (ret.first*=Inv(tmp.first,p_a[i]))%=p_a[i]; (ret.first*=Pow(p[i],ret.second,p_a[i]))%=p_a[i]; China::add(ret.first,p_a[i]); } ans=China::Solve(); write(ans,'\n'); } } int main() { ll Q,order; freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(Q); Work3::Pre(); while (Q--) { read(order); if (order==1) Work1::Solve(); if (order==2) Work2::Solve(); if (order==3) Work3::Solve(); } return 0; }