[MOBAN]二次剩余Cipolla算法
有关二次剩余的cipolla算法模板
原理可见https://blog.csdn.net/qq_33229466/article/details/79125057
int w; const int mod = 1e9+9; namespace MATH { int add(int x,int y) { x+=y; return x>=mod?x-mod:x; } int sub(int x,int y) { x-=y; return x<0?x+mod:x; } int mul(int x,int y) { return 1ll*x*y%mod; } int ksm(int a,int b) { int ans = 1; for(;b;b>>=1,a=mul(a,a)) if(b&1) ans = mul(ans,a); return ans; } } using namespace MATH; struct E{ int re,im; friend E operator*(E aa,E bb) { return (E){ add( mul(aa.re,bb.re) , mul(mul(aa.im,bb.im),w) ) , add( mul(aa.re,bb.im) , mul(aa.im,bb.re)) }; } friend int getksm(E a,int b) { E ans = (E){1,0}; for(;b;b>>=1,a = a*a ) if(b&1) { ans = ans*a; } return ans.re; } }; namespace cipola{ int getit(int n) { int oo = ksm(n,(mod-1)/2); if(oo==mod-1) return -1; if(oo==0) return 0; while(233) { int aa = rand()%mod; if( ksm(sub(mul(aa,aa),n),(mod-1)/2)!=mod-1) continue; w = sub(mul(aa,aa),n); return getksm((E){aa,1},(mod+1)/2); } } }