题面分析
对于集合内的数iii,考虑取多少个它,生成函数为∑j=0infxij=11−xi\sum_{j=0}^{inf} x^{ij}=\frac{1}{1-x^i}∑j=0infxij=1−xi1。
设ti∈[0,1]t_i \in[0,1]ti∈[0,1]表示集合里是否存在数字iii,则fff对应的生成函数就是:
F(x)=∏i=1n(11−xi)tiF(x)=\prod_{i=1}^{n} (\frac{1}{1-x^i})^{t_i}F(x)=i=1∏n(1−xi1)ti
两边同时取ln(为什么想到取ln?我也不知道啊QAQ)得:
−lnF(x)=∑i=1ntiln(1−xi)-\ln{F(x)}=\sum_{i=1}^{n} t_i \ln{(1-x^i)}−lnF(x)=i=1∑ntiln(1−xi)
对ln(1−xi)\ln{(1-x^i)}ln(1−xi)求导得:
−ixi−11−xi\frac{-ix^{i-1}}{1-x^i}1−xi−ixi−1
展开得:(−ixi−1)∑j=0infxji=−∑j=0infixij+i−1(-ix^{i-1})\sum_{j=0}^{inf} x^{ji} = -\sum_{j=0}^{inf} ix^{ij+i-1}(−ixi−1)j=0∑infxji=−j=0∑infixij+i−1
然后积分得:−∑j=0infixi(j+1)i(j+1)=−∑j=1infxijj-\sum_{j=0}^{inf} \frac{ix^{i(j+1)}}{i(j+1)}=-\sum_{j=1}^{inf} \frac{x^{ij}}{j}−j=0∑infi(j+1)ixi(j+1)=−j=1∑infjxij
将ln(1−xi)−∑j=1infxijj\ln{(1-x^i)}-\sum_{j=1}^{inf} \frac{x^{ij}}{j}ln(1−xi)−∑j=1infjxij带入原式得:
lnF(x)=∑i=1nti∑j=1infxijj\ln{F(x)}=\sum_{i=1}^{n}t_i \sum_{j=1}^{inf} \frac{x^{ij}}{j}lnF(x)=i=1∑ntij=1∑infjxij
令T=ijT=ijT=ij,得:
lnF(x)=∑T=1inf(∑d∣TtiiT)xT\ln{F(x)}=\sum_{T=1}^{inf} (\sum_{d|T} t_i \frac{i}{T}) x^TlnF(x)=T=1∑inf(d∣T∑tiTi)xT
设F(x)F(x)F(x)求ln后第iii项为gig_igi,则gi=∑d∣TtiiTg_i=\sum_{d|T} t_i \frac{i}{T}gi=∑d∣TtiTi
那么求tit_iti只用反演即可,发现没必要用莫比乌斯,用每次求出来的tit_iti去减掉它在iii的倍数项的ggg中的贡献,调和级数复杂度地求tit_iti即可。
代码
#include<bits/stdc++.h>
using namespace std;
#define RI register int
int read() {
int q=0;char ch=' ';
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') q=q*10+ch-'0',ch=getchar();
return q;
}
const int N=524300,M=32767;
typedef long long LL;
typedef long double db;
const db pi=acos(-1);
int n,mod,ans;
int rev[N],len[N],F[N],G[N],inv[N];
int k1[N],k2[N],k3[N],k4[N],k5[N];
struct com{db r,i;}a[N],b[N],Aa[N],Ab[N],Ba[N],Bb[N];
com operator + (com A,com B) {return (com){A.r+B.r,A.i+B.i};}
com operator - (com A,com B) {return (com){A.r-B.r,A.i-B.i};}
com operator * (com A,com B) {return (com){A.r*B.r-A.i*B.i,A.r*B.i+A.i*B.r};}
com conj(com A) {return (com){A.r,-A.i};}
int qm(int x) {return x>=mod?x-mod:x;}
int ksm(int x,int y) {
int re=1;
for(;y;y>>=1,x=1LL*x*x%mod) if(y&1) re=1LL*re*x%mod;
return re;
}
void FFT(com *a,int n) {
for(RI i=0;i<n;++i) if(rev[i]>i) swap(a[i],a[rev[i]]);
for(RI i=1;i<n;i<<=1) {
com wn=(com){cos(pi/i),sin(pi/i)};
for(RI j=0;j<n;j+=(i<<1)) {
com t1,t2,w=(com){1,0};
for(RI k=0;k<i;++k,w=w*wn)
t1=a[j+k],t2=w*a[j+i+k],a[j+k]=t1+t2,a[j+i+k]=t1-t2;
}
}
}
void mul(int *ka,int *kb,int *kc,int n) {
for(RI i=0;i<n;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<(len[n]-1));
for(RI i=0;i<(n>>1);++i) {
a[i]=(com){(db)(ka[i]&M),(db)(ka[i]>>15)};
b[i]=(com){(db)(kb[i]&M),(db)(kb[i]>>15)};
a[i+(n>>1)]=b[i+(n>>1)]=(com){0,0};
}
FFT(a,n),FFT(b,n);
for(RI i=0;i<n;++i) {
int j=(n-i)&(n-1);
com kAa=(a[i]+conj(a[j]))*(com){0.5,0};
com kAb=(a[i]-conj(a[j]))*(com){0,-0.5};
com kBa=(b[i]+conj(b[j]))*(com){0.5,0};
com kBb=(b[i]-conj(b[j]))*(com){0,-0.5};
Aa[j]=kAa*kBa,Ab[j]=kAa*kBb,Ba[j]=kBa*kAb,Bb[j]=kAb*kBb;
}
for(RI i=0;i<n;++i)
a[i]=Aa[i]+Ab[i]*(com){0,1},b[i]=Ba[i]+Bb[i]*(com){0,1};
FFT(a,n),FFT(b,n);
for(RI i=0;i<n;++i) {
int kAa=(LL)(a[i].r/n+0.5)%mod;
int kAb=(LL)(a[i].i/n+0.5)%mod;
int kBa=(LL)(b[i].r/n+0.5)%mod;
int kBb=(LL)(b[i].i/n+0.5)%mod;
kc[i]=qm(((LL)kAa+((LL)(kAb+kBa)<<15)+((LL)kBb<<30))%mod+mod);
}
}
void getJF(int *a,int *b,int n)
{for(RI i=1;i<n;++i) b[i]=1LL*a[i-1]*inv[i]%mod; b[0]=0;}
void getdao(int *a,int *b,int n)
{for(RI i=1;i<n;++i) b[i-1]=1LL*a[i]*i%mod; b[n-1]=0;}
void getinv(int *a,int *b,int n) {
if(n==1) {b[0]=ksm(a[0],mod-2);return;}
getinv(a,b,n>>1),mul(a,b,k3,n<<1),mul(k3,b,k4,n<<1);
for(RI i=0;i<n;++i) b[i]=qm(qm(b[i]+b[i])-k4[i]+mod),b[i+n]=0;
}
void getln(int *a,int *b,int n)
{getdao(a,k1,n),getinv(a,k2,n),mul(k1,k2,k5,n<<1),getJF(k5,b,n);}
int main()
{
n=read(),mod=read();
for(RI i=1;i<=n;++i) F[i]=read();
int kn=1;while(kn<=n) kn<<=1,len[kn]=len[kn>>1]+1;
len[kn<<1]=len[kn]+1;
inv[1]=1;for(RI i=2;i<(kn<<1);++i) inv[i]=1LL*inv[mod%i]*qm(mod-mod/i)%mod;
F[0]=1,getln(F,G,kn);
for(RI i=1;i<=n;++i) G[i]=1LL*G[i]*i%mod;
for(RI i=1;i<=n;++i)
for(RI j=i+i;j<=n;j+=i) G[j]=qm(G[j]-G[i]+mod);
for(RI i=1;i<=n;++i) if(G[i]) ++ans;
printf("%d\n",ans);
for(RI i=1;i<=n;++i) if(G[i]) printf("%d ",i);
return 0;
}