CF264B Good Sequences
Posted ppxppx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF264B Good Sequences相关的知识,希望对你有一定的参考价值。
题意:求一个最长的序列,满足序列严格单调递增,任意相邻两个数非互质且所有的数都来自长度为n且单调递增的序列a三个条件.
分析:既然原序列本身满足单调递增,所以对于这个条件我们可以不管.所有的数都来自a序列,额,这个条件更没必要管.所以我们从序列相邻两个数非互质入手.
设f[i]表示以a[i]结尾的合法序列的最大长度,转移方程不难想到:(f[i]=max(f[j])+1),其中(gcd(a[i],a[j])>1)
但是如果O(n)枚举a[i],然后每一次转移的时候让当前的a[i]O(n)地跟所有数比较一边,判断是否满足非互质,是否最优,总的时间复杂度是(n^2),肯定超时.
注意到本题a1,a2...an<=(10^5),既然数值这么小(数组都能开到这么大),我们就可以考虑在ai上做文章.两个数x,y非互质,即gcd(x,y)>1,即x和y有相同的质因子,所以我们可以预处理出(10^5)内所有的质数.
然后直接1-n枚举序列a,假设当前已经考虑到了ai这个数,我们再枚举所有预处理出的质数,如果当前的a[i]能被当前枚举到的这个质数pri[j]整除,则f[i]一定只能从f[k]转移过来,其中a[k]也能被pri[j]整除且k<i.
所以我们可以开一个vector队列q,q[pri[j]]存的是序列a中所有能被pri[j]整除的数的下标,因为我们从小到大枚举a[i],而q[pri[j]]是随着我们的枚举才会不断更新的,所以q[pri[j]]里面的下标肯定是单调递增的.
根据q数组的递增性和题目要求的最优性,如果f[i]可以被pri[j]整除,且q[pri[j]].size()不为零(即在之前的枚举中已经找到了至少一个k,使得a[k]也能被pri[j]整除),则f[i]一定是从q[pri[j]]中的最后一个数(q[pri[j]][q[pri[j]].size()-1])转移过来.
每一次转移完之后别忘了更新q数组.
P.S.我知道我上面的分析讲得很不清楚,就这么几句话挤了半个多小时才写出来,可能是因为我也不理解这道题吧,所以真的写的很烂...
const int MAXN=100005;
int n,m,ans;
int a[MAXN],v[MAXN],pri[MAXN],f[MAXN];
vector<int> q[MAXN];
//q[i]记录的是序列a中所有能被i整除的数的下标
//线性筛素数
void get_prime(){
v[1]=1;
for(int i=2;i<=MAXN;i++){
if(!v[i]){
pri[++m]=i;
v[i]=i;
}
for(int j=1;j<=m;j++){
if(pri[j]>v[i]||i*pri[j]>MAXN)
break;
v[i*pri[j]]=pri[j];
}
}
}
int main(){
get_prime();
n=read();
for(int i=1;i<=n;i++)a[i]=read();
for(int i=1;i<=n;i++){//枚举序列a
int now=a[i];
for(int j=1;j<=m;j++){//枚举所有质数
if(now%pri[j]==0){
//如果now能够被pri[j]整除,a[i]肯定也能被pri[j]整除
while(now%pri[j]==0)now/=pri[j];
//这里与下面代码中if(now<pri[j])break;相照应
//是为了优化时间
int cnt=q[pri[j]].size();
if(cnt)f[i]=max(f[i],f[q[pri[j]][cnt-1]]+1);
//如果cnt不为零,即之前已经存在a[k]能够被pri[j]整除
//则f[i]可以从q[pri[j]]中的最后一个数转移
else f[i]=max(f[i],1);
//否则,说明之前枚举的所有的a[k]
//与当前的a[i]的共同的质因子不包括pri[j]
//即f[i]无法从前面转移过来
q[pri[j]].push_back(i);
//既然当前的a[i]能被pri[j]整除,就可以更新q[pri[j]]
}
if(now<pri[j])break;
//如果now已经比当前的pri[j]小,
//pri数组里的质数肯定是单调递增的,
//后面就更不会有比now还小的质数了,
//即后面肯定不存在j,使得now%pri[j]=0了,直接退出
}
}
for(int i=1;i<=n;i++)ans=max(ans,f[i]);
if(!ans)puts("1");//序列只有一个数显然成立
else printf("%d
",ans);
return 0;
}
以上是关于CF264B Good Sequences的主要内容,如果未能解决你的问题,请参考以下文章
[CF1030E]Vasya and Good Sequences
CF1030E Vasya and Good Sequences 最大值分治/容斥
Codeforces 1053 B - Vasya and Good Sequences