noip 模拟32 Six
这道题思路比较新奇,题解用了一个质因子对的概念:
顾名思义,两个质数,且出现在序列中不同的数当中。
这有什么用呢?
我们可以通过判断新加入的数与原序列的质因子的集合并集中是否有这样的质因子对,来确定新加入的数是否符合条件。
具体来说就是,取 A{ 新加入的数的质因子 } & B{ 原序列的质因子 } = S ,看原序列中是否已经出现过S中的质因子对,如果出现过,那这个数就一定和原序列中至少两个数不互质,所以不符合条件。
题目的精髓太该就是这样,剩下的预处理还是很简单的。
因为质因子个数较少,质因子对数也最多有 \(\sum_{i=1}^{n} i\) 个,所以把质因子对数也状压起来好了。
inline int dfs(int sum_tmp,int tmps) { // 质因子的集合状态 | 质因子对的集合状态
if((x=dp[pir(sum_tmp,tmps)])) return x; // 记搜
int ans=0;
for(re int is=1,tmp,s;is<=top;is++) { // 枚举n的约数
tmp=ds[is]&sum_tmp;
if(pr[tmp]&tmps) continue;
s=0;
for(re int i=1;i<=cnt;i++) if(ds[is]&(1<<i-1)) // 枚举质因子对
for(re int j=1;j<=cnt;j++) if(sum_tmp&(1<<j-1))
s|=(1<<tran[i][j]-1);
(ans+=dfs(ds[is]|sum_tmp,s|tmps))%=mol; // 更新
}
return dp[pir(sum_tmp,tmps)]=(ans+1)%mol;
}
最关键的,证明复杂度。
首先要知道约数的个数 \(d(x)\),若 \(n=\prod_{i=1}^{cnt}p_{i}^{c_{i}}\) ,则 \(d(n)=\prod_{i=1}^{cnt}(c_{i}+1)\)。
考虑最坏情况, \(c_{i}\) 最大为50左右,再均摊,则约数最大个数为 \((\frac{50}{6}+1)^{6}\),
则状态数最多为 \(2^{6}*(\frac{50}{6}+1)^{6}\),证毕。
其实是假的,我也不知道一共有多少状态数,但约数个数是真的,我们至少有个上限了。