i207M
2020-08-20 08:09:03
退役选手学IO啦...
我太笨了,竟然忘了埃氏筛怎么写(要从
Learn from this
关于原根的一些小知识:
设
设
模
若
首先我们要求出最小原根,有性质:最小原根不大于
求出原根之后,我们再找出与
使用基数排序加速。最终复杂度小于
const int N=1e6+5;
bitset<N> notp;
int p[N], cntp;
int phi[N];
bitset<N*2> exi;
void shai(int n)
{
notp[1]=1;
for(int i=2; i<=n; ++i)
{
if(!notp[i])
{
p[++cntp]=i;
phi[i]=i-1;
}
for(int j=1, t; j<=cntp&&(t=p[j]*i)<=n; ++j)
{
notp[t]=1;
if(i%p[j]==0)
{
phi[t]=phi[i]*p[j];
break;
}
phi[t]=phi[i]*(p[j]-1);
}
}
exi[2]=exi[4]=1;
for(int i=1; i<=cntp; ++i)
for(LL j=p[i]; j<=n; j*=p[i])
exi[j]=1, exi[j<<1]=1;
}
int fac[50], cntf;
bitset<N> notg;
void dofac(int n)
{
int _n=n;
for(int i=1; i<=cntp&&p[i]<=n; ++i)
{
if(n%p[i]==0)
{
int tp=p[i];
fac[++cntf]=tp;
while(n%tp==0) n/=tp;
for(int j=tp; j<=_n; j+=tp) notg[j]=1;
}
}
}
int getg(int n)
{
bool flg;
for(int i=2;; ++i)
{
if(gcd(i, n)!=1) continue;
flg=1;
for(int j=1; j<=cntf; ++j)
if(qpow(i, phi[n]/fac[j], n)==1) {flg=0; break;}
if(flg) return i;
}
}
bitset<N> buk;
int v[N], cntv;
void clear()
{
cntf=cntv=0;
notg.reset();
buk.reset();
}
void solve(int n, int d)
{
if(n==2)
{
puts("1");
puts(d==1?"1":"");
return;
}
if(!exi[n])
{
puts("0\n");
return;
}
int m=phi[n];
dofac(m);
int g=getg(n);
for(int i=1; i<m; ++i)
if(!notg[i])
{
buk[qpow(g, i, n)]=1;
}
for(int i=1; i<=n; ++i)
if(buk[i])
{
v[++cntv]=i;
}
out(cntv);
for(int i=d; i<=cntv; i+=d) out(v[i], ' ');
enter;
clear();
}