[luogu5616]恶魔之树
记录$lcm$的质因子状态(包括大于$\sqrt 300$的质因子),设$f[s]$表示质因子状态为$s$的$lcm$之和,转移枚举当前的数$k$,转移到$lcm(s,k)$即可,时间复杂度为$o(n\cdot |stats|)$($|stats|$会非常大)
优化1:对于一个$k$,有$2^{cnt}-1$种方案转移到$lcm(s,k)$($cnt$为$k$出现次数),而$k$最多300个,因此时间复杂度降为$o(300\cdot |stats|)$
优化2:对于一个$k$,我们只关心$k$所含有的质因子,也就是说设令$g[s]=\sum_{s\in s'}f[s']$(理解一下,$s$中仅表示2,3,5,7,11,13,17以及$k$中含有的大质数,$s'$表示全部状态,$s\in s'$即在$s$考虑的质数与$s'$对应的质数状态相同),那么可以直接在$g$上转移
答案即求$\sum_{s}f[s]$,由于对于19即以上的质因子,同一个数$k$不可能同时存在2个/种,因此从小到大枚举质因子,再枚举含有该质因子的数,对于已经其余的质因子通过上述方式压缩即可,$|stats|$为17496,复杂度可以通过
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 305 4 #define STA 17496 5 #define ll long long 6 struct ji{ 7 int a[11]; 8 }o; 9 int n,x,mod,a[N],vis[N],mi[300005],w[STA],p[7]={2,3,5,7,11,13,17}; 10 ll ans,f[STA][2]; 11 void add(ll &x,int y){ 12 x=(x+y)%mod; 13 } 14 int hash(ji k){ 15 return k.a[6]+3*k.a[5]+9*k.a[4]+27*k.a[3]+81*k.a[2]+324*k.a[1]+1944*k.a[0]; 16 } 17 ji inv_hash(int k){ 18 ji ans; 19 ans.a[0]=k/1944; 20 ans.a[1]=k%1944/324; 21 ans.a[2]=k%324/81; 22 ans.a[3]=k%81/27; 23 ans.a[4]=k%27/9; 24 ans.a[5]=k%9/3; 25 ans.a[6]=k%3; 26 return ans; 27 } 28 ji dec(ji x,ji y){ 29 ji ans; 30 for(int i=0;i<7;i++)ans.a[i]=max(x.a[i]-y.a[i],0); 31 return ans; 32 } 33 ji mx(ji x,ji y){ 34 ji ans; 35 for(int i=0;i<7;i++)ans.a[i]=max(x.a[i],y.a[i]); 36 return ans; 37 } 38 ji div(int k){ 39 ji ans; 40 for(int i=0;i<7;i++){ 41 ans.a[i]=0; 42 while (k%p[i]==0){ 43 k/=p[i]; 44 ans.a[i]++; 45 } 46 } 47 return ans; 48 } 49 int main(){ 50 scanf("%d%d",&n,&mod); 51 mi[0]=w[0]=1; 52 for(int i=1;i<=n;i++)mi[i]=2LL*mi[i-1]%mod; 53 for(int i=1;i<STA;i++){ 54 o=inv_hash(i); 55 for(int j=0;j<7;j++) 56 if (o.a[j]){ 57 o.a[j]--; 58 w[i]=1LL*w[hash(o)]*p[j]%mod; 59 break; 60 } 61 } 62 for(int i=1;i<=n;i++){ 63 scanf("%d",&x); 64 a[x]++; 65 } 66 f[0][0]=1; 67 for(int i=1;i<N-4;i++) 68 if (w[hash(div(i))]==i){ 69 o=div(i); 70 for(int j=STA-1;j>=0;j--)add(f[hash(mx(o,inv_hash(j)))][0],f[j][0]*(mi[a[i]]-1)%mod); 71 } 72 for(int i=0;i<STA;i++)f[i][0]=f[i][0]*w[i]%mod; 73 for(int i=19;i<N-4;i++){ 74 if (w[hash(div(i))]>1)continue; 75 for(int j=i;j<N-4;j+=i){ 76 o=div(j); 77 for(int k=STA-1;k>=0;k--) 78 add(f[hash(mx(o,inv_hash(k)))][1],(i*f[k][0]+f[k][1])%mod*w[hash(dec(o,inv_hash(k)))]%mod*(mi[a[j]]-1)%mod); 79 } 80 for(int j=0;j<STA;j++){ 81 add(f[j][0],f[j][1]); 82 f[j][1]=0; 83 } 84 } 85 for(int i=0;i<STA;i++)add(ans,f[i][0]); 86 printf("%d",ans); 87 }