// Submission (TLE): https://judge.yosupo.jp/submission/320582#include<algorithm>#include<cmath>#include<iostream>#include<tuple>#include<unordered_map>#include<vector>structPrimePower{intp,e,pe;PrimePower(intp,inte,intpe):p(p),e(e),pe(pe){}};// Factorization.autofactorize(intn){std::vector<PrimePower>ans;for(intx=2;x*x<=n;++x){inte=0,pe=1;for(;n%x==0;n/=x,++e,pe*=x);if(e)ans.emplace_back(x,e,pe);}if(n>1)ans.emplace_back(n,1,n);returnans;}// Binary exponentiation.intpow(inta,intb,intm=0){intres=1;for(;b;b>>=1){if(b&1)res=m?(longlong)res*a%m:res*a;a=m?(longlong)a*a%m:a*a;}returnres;}// Find a primitive root modulo prime.intprimitive_root(intp){std::vector<int>exp;for(autofactor:factorize(p-1)){exp.push_back((p-1)/factor.p);}intans=0;boolsucc=false;while(!succ){++ans;succ=true;for(intb:exp){if(pow(ans,b,p)==1){succ=false;break;}}}returnans;}// Discrete logarithm. (BSGS Algorithm)intlog(intg,inta,intm){intb=std::sqrt(m+0.25l)+1;std::unordered_map<int,int>mp;intpo0=a%m,po1=1;for(inti=0;i<b;++i){mp[po0]=i;po0=(longlong)po0*g%m;}po0=pow(g,b,m);for(intj=1;j<=b;++j){po1=(longlong)po1*po0%m;if(mp.count(po1))returnj*b-mp[po1];}return-1;}// Extended Euclidean Algorithm.intex_gcd(inta,intb,int&x,int&y){if(!b){x=1;y=0;returna;}else{intd=ex_gcd(b,a%b,y,x);y-=a/b*x;returnd;}}// Solves the linear congruence equation: Ax = B mod N.// Return the least nonnegative solution and the common difference.std::pair<int,int>solve_linear(inta,intb,intn){intx,y;intd=ex_gcd(a,n,x,y);if(b%d)return{-1,-1};n/=d;x=((longlong)x*(b/d)%n+n)%n;return{x,n};}// Subroutine: Find a K-th root with a primitive root G known.intcalc(intg,intk,inta,intp){intind=log(g,a,p);if(ind==-1)return-1;inty0,d;std::tie(y0,d)=solve_linear(k,ind,p-1);if(y0==-1)return-1;returnpow(g,y0,p);}// Find a K-th root of A modulo prime P.intkth_roots_mod_p(intk,inta,intp){a%=p;if(k==0)returna==1?0:-1;if(a==0)return0;returncalc(primitive_root(p),k,a,p);}voidsolve(){intk,y,p;std::cin>>k>>y>>p;std::cout<<kth_roots_mod_p(k,y,p)<<'\n';}intmain(){intt;std::cin>>t;for(;t;--t){solve();}}
#include<algorithm>#include<cmath>#include<iostream>#include<random>#include<tuple>#include<unordered_map>#include<vector>std::mt19937rng(std::random_device{}());// Binary exponentiation.intpow(inta,intb,intm=0){intres=1;for(;b;b>>=1){if(b&1)res=m?(longlong)res*a%m:res*a;a=m?(longlong)a*a%m:a*a;}returnres;}// Find a P-th non-residue mod M.intnon_residue(intp,intm,intphi){std::uniform_int_distribution<int>dis(1,m-1);while(true){intc=dis(rng);if(pow(c,phi/p,m)!=1)returnc;}return-1;}// Euclidean Algorithm.intgcd(inta,intb){returnb?gcd(b,a%b):a;}// Extended Euclidean Algorithm.intex_gcd(inta,intb,int&x,int&y){if(!b){x=1;y=0;returna;}else{intd=ex_gcd(b,a%b,y,x);y-=a/b*x;returnd;}}// Returns the modular inverse of A modulo M.// Assumes that gcd(A, M) = 1, so the inverse exists.intinv(inta,intm){intx,y;ex_gcd(a,m,x,y);return(x%m+m)%m;}// Subroutine: Find a P^E-th root of A mod M.intpeth_root_mod_m(intp,inte,inta,intm,intphi){ints=0,r=phi,pe=pow(p,e);for(;r%p==0;r/=p,++s);intq=pe-inv(r,pe);intans=pow(a,((longlong)q*r+1)/pe%phi,m);inteta=non_residue(p,m,phi);std::unordered_map<int,int>mp;intzeta=pow(eta,r,m);intxi=pow(eta,phi/p,m);// Precompute powers for BSGS.intB=std::sqrt((s-e)*p+0.25l)+1;intpB=p/B+1;intpo0=pow(xi,pB,m);for(intj=1,po1=1;j<=B;++j){po1=(longlong)po1*po0%m;mp[po1]=j;}// Compute p-adic digits of h.for(intj=0;j<s-e;++j){interr=(longlong)pow(ans,pe,m)*inv(a,m)%m;intxi_hj=pow(err,pow(p,s-e-j-1),m);longlonghj=0;// BSGS query.for(inti=1;i<=pB;++i){xi_hj=(longlong)xi_hj*xi%m;if(mp.count(xi_hj)){hj=mp[xi_hj]*pB-i;break;}}ans=(longlong)ans*pow(zeta,phi-hj*pow(p,j)%phi,m)%m;}returnans;}// Find a K-th root of A modulo prime P.intkth_root_mod_p(intk,inta,intp){a%=p;if(k==0)returna==1?0:-1;if(a==0)return0;intd=gcd(k,p-1);if(pow(a,(p-1)/d,p)!=1)return-1;a=pow(a,inv(k/d,(p-1)/d),p);for(intdp=2;dp*dp<=d&&dp*dp*dp*dp<p;++dp){if(d%dp==0){intde=0;for(;d%dp==0;d/=dp,++de);a=peth_root_mod_m(dp,de,a,p,p-1);}}if(d!=1){intdp=gcd(d,(p-1)/d),de=0;if(dp!=1){for(;d%dp==0;d/=dp,++de);a=peth_root_mod_m(dp,de,a,p,p-1);}if(d!=1)a=peth_root_mod_m(d,1,a,p,p-1);}returna;}voidsolve(){intk,y,p;std::cin>>k>>y>>p;std::cout<<kth_root_mod_p(k,y,p)<<'\n';}intmain(){intt;std::cin>>t;for(;t;--t){solve();}}
#include<algorithm>#include<cmath>#include<iostream>#include<tuple>#include<unordered_map>#include<vector>structPrimePower{intp,e,pe;PrimePower(intp,inte,intpe):p(p),e(e),pe(pe){}};// Factorization.autofactorize(intn){std::vector<PrimePower>ans;for(intx=2;x*x<=n;++x){inte=0,pe=1;for(;n%x==0;n/=x,++e,pe*=x);if(e)ans.emplace_back(x,e,pe);}if(n>1)ans.emplace_back(n,1,n);returnans;}// Binary exponentiation.intpow(inta,intb,intm=0){intres=1;for(;b;b>>=1){if(b&1)res=m?(longlong)res*a%m:res*a;a=m?(longlong)a*a%m:a*a;}returnres;}// Find a primitive root modulo odd prime power.intprimitive_root(PrimePowerpp){std::vector<int>exp;intphi=pp.pe/pp.p*(pp.p-1);for(autofactor:factorize(pp.p-1)){exp.push_back(phi/factor.p);}if(pp.e!=1)exp.push_back(phi/pp.p);intans=0;boolsucc=false;while(!succ){++ans;succ=true;for(intb:exp){if(pow(ans,b,pp.pe)==1){succ=false;break;}}}returnans;}// Discrete logarithm. (BSGS Algorithm)intlog(intg,inta,intm){intb=std::sqrt(m+0.25l)+1;std::unordered_map<int,int>mp;intpo0=a%m,po1=1;for(inti=0;i<b;++i){mp[po0]=i;po0=(longlong)po0*g%m;}po0=pow(g,b,m);for(intj=1;j<=b;++j){po1=(longlong)po1*po0%m;if(mp.count(po1))returnj*b-mp[po1];}return-1;}// Extended Euclidean Algorithm.intex_gcd(inta,intb,int&x,int&y){if(!b){x=1;y=0;returna;}else{intd=ex_gcd(b,a%b,y,x);y-=a/b*x;returnd;}}// Returns the modular inverse of A modulo M.// Assumes that gcd(A, M) = 1, so the inverse exists.intinv(inta,intm){intx,y;ex_gcd(a,m,x,y);return(x%m+m)%m;}// Solves the linear congruence equation: Ax = B mod N.// Return the least nonnegative solution and the common difference.std::pair<int,int>solve_linear(inta,intb,intn){intx,y;intd=ex_gcd(a,n,x,y);if(b%d)return{-1,-1};n/=d;x=((longlong)x*(b/d)%n+n)%n;return{x,n};}// Subroutine: Find all the K-th roots with a primitive root G known.std::vector<int>calc(intg,intk,inta,intp,intpe){intind=log(g,a,pe);if(ind==-1)return{};intmm=p==2?pe/4:pe/p*(p-1);inty0,d;std::tie(y0,d)=solve_linear(k,ind,mm);if(y0==-1)return{};intans=pow(g,y0,pe),po=pow(g,d,pe);std::vector<int>res(mm/d);for(auto&x:res){x=ans;ans=(longlong)ans*po%pe;}returnres;}// Find all the K-th roots of A modulo prime power P^E.std::vector<int>kth_roots_mod_pe(intk,inta,PrimePowerpp){intp=pp.p,e=pp.e,pe=pp.pe;a%=pe;if(a==0){intd=pow(p,(e-1)/k+1);std::vector<int>res(pe/d);for(inti=0;i<pe/d;++i){res[i]=i*d;}returnres;}ints=0;for(;a%p==0;a/=p,++s);if(s%k)return{};intpsk=pow(p,s/k),pss=pow(p,s-s/k),pes=pow(p,e-s);std::vector<int>res;if(p!=2){intg=primitive_root(PrimePower(p,e-s,pes));res=calc(g,k,a,p,pes);}elseif(pes==2){res.push_back(a);}elseif(k&1){intz=a%4==3;a=z?pes-a:a;res=calc(5,k,a,p,pes);if(z){for(auto&x:res)x=pes-x;}}else{if(a%4==3)return{};res=calc(5,k,a,p,pes);intm=res.size();res.reserve(m*2);for(inti=0;i<m;++i){res.push_back(pes-res[i]);}}intm=res.size();res.reserve(m*pss);for(intj=1;j<pss;++j){for(inti=0;i<m;++i){res.push_back(res.end()[-m]+pes);}}for(auto&x:res)x*=psk;returnres;}// Find all the K-th roots of A modulo positive integer M.std::vector<int>kth_roots_mod_m(intk,inta,intm){autofactors=factorize(m);intm0=0;std::vector<std::vector<int>>sols;for(constauto&pp:factors){sols.push_back(kth_roots_mod_pe(k,a,pp));if(sols.back().empty())return{};}std::vector<int>ans;for(inti=0;i<(int)factors.size();++i){autopp=factors[i];if(!i){m0=pp.pe;ans=sols[i];}else{longlongm1=pp.pe*inv(pp.pe,m0);longlongm2=m0*inv(m0,pp.pe);m0*=pp.pe;std::vector<int>_ans;_ans.reserve(ans.size()*sols[i].size());for(autox:ans){for(autoy:sols[i]){_ans.push_back((m1*x+m2*y)%m0);}}ans.swap(_ans);}}returnans;}voidsolve(){intn,m,k;std::cin>>n>>m>>k;autoans=kth_roots_mod_m(n,k,m);if(ans.empty()){std::cout<<0<<'\n';return;}std::cout<<ans.size()<<'\n';std::sort(ans.begin(),ans.end());for(autox:ans)std::cout<<x<<' ';std::cout<<'\n';}intmain(){intt;std::cin>>t;for(;t;--t){solve();}}
#include<algorithm>#include<cmath>#include<iostream>#include<random>#include<tuple>#include<unordered_map>#include<vector>std::mt19937rng(std::random_device{}());structPrimePower{intp,e,pe;PrimePower(intp,inte,intpe):p(p),e(e),pe(pe){}};// Factorization.autofactorize(intn){std::vector<PrimePower>ans;for(intx=2;x*x<=n;++x){inte=0,pe=1;for(;n%x==0;n/=x,++e,pe*=x);if(e)ans.emplace_back(x,e,pe);}if(n>1)ans.emplace_back(n,1,n);returnans;}// Binary exponentiation.intpow(inta,intb,intm=0){intres=1;for(;b;b>>=1){if(b&1)res=m?(longlong)res*a%m:res*a;a=m?(longlong)a*a%m:a*a;}returnres;}// Find a primitive root modulo odd prime power.intprimitive_root(PrimePowerpp){std::vector<int>exp;intphi=pp.pe/pp.p*(pp.p-1);for(autofactor:factorize(pp.p-1)){exp.push_back(phi/factor.p);}if(pp.e!=1)exp.push_back(phi/pp.p);intans=0;boolsucc=false;while(!succ){++ans;succ=true;for(intb:exp){if(pow(ans,b,pp.pe)==1){succ=false;break;}}}returnans;}// Euclidean Algorithm.intgcd(inta,intb){returnb?gcd(b,a%b):a;}// Extended Euclidean Algorithm.intex_gcd(inta,intb,int&x,int&y){if(!b){x=1;y=0;returna;}else{intd=ex_gcd(b,a%b,y,x);y-=a/b*x;returnd;}}// Returns the modular inverse of A modulo M.// Assumes that gcd(A, M) = 1, so the inverse exists.intinv(inta,intm){intx,y;ex_gcd(a,m,x,y);return(x%m+m)%m;}// Find a P-th non-residue mod M.intnon_residue(intp,intm,intphi){std::uniform_int_distribution<int>dis(1,m-1);while(true){intc=dis(rng);if(gcd(c,m)==1&&pow(c,phi/p,m)!=1)returnc;}return-1;}// Subroutine: Find a P^E-th root of A mod M.intpeth_root_mod_m(intp,inte,inta,intm,intphi){if(m==2)return1;ints=0,r=phi,pe=pow(p,e);for(;r%p==0;r/=p,++s);intq=pe-inv(r,pe);intans=pow(a,((longlong)q*r+1)/pe%phi,m);inteta=non_residue(p,m,phi);std::unordered_map<int,int>mp;intzeta=pow(eta,r,m);intxi=pow(eta,phi/p,m);// Precompute powers for BSGS.intB=std::sqrt((s-e)*p+0.25l)+1;intpB=pe/B+1;intpo0=pow(xi,pB,m);for(intj=1,po1=1;j<=B;++j){po1=(longlong)po1*po0%m;mp[po1]=j;}// Compute p-adic digits of h.for(intj=0;j<s-e;++j){interr=(longlong)pow(ans,pe,m)*inv(a,m)%m;intxi_hj=pow(err,pow(p,s-e-j-1),m);longlonghj=0;// BSGS query.for(inti=1;i<=pB;++i){xi_hj=(longlong)xi_hj*xi%m;if(mp.count(xi_hj)){hj=mp[xi_hj]*pB-i;break;}}ans=(longlong)ans*pow(zeta,phi-hj*pow(p,j)%phi,m)%m;}returnans;}// Find a K-th root of A modulo prime P^E.intkth_root_mod_pe(intk,inta,intpe,intphi){a%=pe;if(k==0)returna==1?0:-1;if(a==0)return0;intd=gcd(k,phi);if(pow(a,phi/d,pe)!=1)return-1;a=pow(a,inv(k/d,phi/d),pe);for(intdp=2;dp*dp<=d&&dp*dp*dp*dp<pe;++dp){if(d%dp==0){intde=0;for(;d%dp==0;d/=dp,++de);a=peth_root_mod_m(dp,de,a,pe,phi);}}if(d!=1){intdp=gcd(d,phi/d),de=0;if(dp!=1){for(;d%dp==0;d/=dp,++de);a=peth_root_mod_m(dp,de,a,pe,phi);}if(d!=1)a=peth_root_mod_m(d,1,a,pe,phi);}returna;}// Subroutine: Find all the K-th roots with a primitive root G known.std::vector<int>calc(intg,intk,inta,intp,intpe){intmm=p==2?pe/4:pe/p*(p-1);intans=kth_root_mod_pe(k,a,pe,mm);if(ans==-1)return{};intd=mm/gcd(k,mm);intpo=pow(g,d,pe);std::vector<int>res(mm/d);for(auto&x:res){x=ans;ans=(longlong)ans*po%pe;}returnres;}// Find all the K-th roots of A modulo prime power P^E.std::vector<int>kth_roots_mod_pe(intk,inta,PrimePowerpp){intp=pp.p,e=pp.e,pe=pp.pe;a%=pe;if(a==0){intd=pow(p,(e-1)/k+1);std::vector<int>res(pe/d);for(inti=0;i<pe/d;++i){res[i]=i*d;}returnres;}ints=0;for(;a%p==0;a/=p,++s);if(s%k)return{};intpsk=pow(p,s/k),pss=pow(p,s-s/k),pes=pow(p,e-s);std::vector<int>res;if(p!=2){intg=primitive_root(PrimePower(p,e-s,pes));res=calc(g,k,a,p,pes);}elseif(pes==2){res.push_back(a);}elseif(k&1){intz=a%4==3;a=z?pes-a:a;res=calc(5,k,a,p,pes);if(z){for(auto&x:res)x=pes-x;}}else{if(a%4==3)return{};res=calc(5,k,a,p,pes);intm=res.size();res.reserve(m*2);for(inti=0;i<m;++i){res.push_back(pes-res[i]);}}intm=res.size();res.reserve(m*pss);for(intj=1;j<pss;++j){for(inti=0;i<m;++i){res.push_back(res.end()[-m]+pes);}}for(auto&x:res)x*=psk;returnres;}// Find all the K-th roots of A modulo positive integer M.std::vector<int>kth_roots_mod_m(intk,inta,intm){autofactors=factorize(m);intm0=0;std::vector<std::vector<int>>sols;for(constauto&pp:factors){sols.push_back(kth_roots_mod_pe(k,a,pp));if(sols.back().empty())return{};}std::vector<int>ans;for(inti=0;i<(int)factors.size();++i){autopp=factors[i];if(!i){m0=pp.pe;ans=sols[i];}else{longlongm1=pp.pe*inv(pp.pe,m0);longlongm2=m0*inv(m0,pp.pe);m0*=pp.pe;std::vector<int>_ans;_ans.reserve(ans.size()*sols[i].size());for(autox:ans){for(autoy:sols[i]){_ans.push_back((m1*x+m2*y)%m0);}}ans.swap(_ans);}}returnans;}voidsolve(){intn,m,k;std::cin>>n>>m>>k;autoans=kth_roots_mod_m(n,k,m);if(ans.empty()){std::cout<<0<<'\n';return;}std::cout<<ans.size()<<'\n';std::sort(ans.begin(),ans.end());for(autox:ans)std::cout<<x<<' ';std::cout<<'\n';}intmain(){intt;std::cin>>t;for(;t;--t){solve();}}
根据 原根个数相关结论 可知,𝜆‑原根的数量恰为 𝜑(𝜆(𝑚)),其中,𝜑(⋅) 和 𝜆(⋅) 分别是欧拉函数和 Carmichael 函数。因为对于几乎所有整数 𝑚,都有 𝜆(𝑚)/𝑚=exp(−(1+𝑜(1))loglog𝑚logloglog𝑚),而存在 𝐶>0,使得对于整数 𝑚>2,都有 𝜑(𝑚)/𝑚=𝐶/loglog𝑚,所以,对于几乎所有整数 𝑚,都有 𝜑(𝜆(𝑚))/𝑚=exp(−(1+𝑜(1))loglog𝑚logloglog𝑚)。其中,指数部分系数中的 𝑜(1) 吸收了因子 𝜑(𝜆(𝑚))/𝜆(𝑚) 的贡献。故而,𝜆‑原根可以在期望 exp((1+𝑜(1))loglog𝑚logloglog𝑚) 次内找到。关于欧拉函数的估计,可以参考论文 Rosser, J. Barkley, and Lowell Schoenfeld. "Approximate formulas for some functions of prime numbers." Illinois Journal of Mathematics 6, no. 1 (1962): 64-94.关于 Carmichael 函数的估计,可以参考论文 Erdos, Paul, Carl Pomerance, and Eric Schmutz. "Carmichael’s lambda function." Acta Arith 58, no. 4 (1991): 363-385. ↩
原始论文参见 Adleman, Leonard, Kenneth Manders, and Gary Miller. "On taking roots in finite fields." In 18th Annual Symposium on Foundations of Computer Science (sfcs 1977), pp. 175-178. IEEE Computer Society, 1977.一个更易读的介绍可见于 Cao, Zhengjun, Qian Sha, and Xiao Fan. "Adleman-Manders-Miller root extraction method revisited." In International Conference on Information Security and Cryptology, pp. 77-85. Berlin, Heidelberg: Springer Berlin Heidelberg, 2011. ↩