线性筛+dp
用埃氏筛好像过不去。。可能是我写的dp太慢了。。
首先可以确定的是这题是可以dp的,对于每个数num[i],将其质因子分解出来,对于每个质因子pi,找到[1..i-1]里所有可以被pi整除的位置pos,用mi[pos-1]去更新mi[i]即可
向右扫描的时候维护一个pos[]数组,pos[i]表示质因子i出现的所有位置x中,mi[x-1]最小的那个
class Solution { public: #define N 1000005 #define maxn 1000005 int prime[1000005],m; bool vis[maxn]; void init(){ for(int i=2;i<maxn;i++){ if(!vis[i]){ prime[++m]=i; } for(int j=1;j<=m;j++){ if(prime[j]*i>=maxn)break; vis[prime[j]*i]=1; if(i%prime[j]==0) break; } } } int p[N],mm; void divide(int x){ mm=0; for(int i=1;i<=m && prime[i]*prime[i]<=x;i++) if(x%prime[i]==0){ p[++mm]=prime[i]; while(x%prime[i]==0)x/=prime[i]; } if(x>1)p[++mm]=x; } int mi[N],pos[N];//mi[i]表示i结尾的最小值,pos[i]表示素数i最右的被当成数组结尾的位置 int splitArray(vector<int>& nums) { init(); int n=nums.size(); for(int i=0;i<=1e6;i++)mi[i]=pos[i]=1e8; divide(nums[0]); for(int i=1;i<=mm;i++){ mi[0]=1;pos[p[i]]=0; } for(int i=1;i<n;i++){ divide(nums[i]); mi[i]=min(mi[i],mi[i-1]+1); for(int j=1;j<=mm;j++){ if(pos[p[j]]==1e8)continue; if(pos[p[j]]==0)mi[i]=1; else mi[i]=min(mi[i],mi[pos[p[j]]-1]+1); } for(int j=1;j<=mm;j++){ if(pos[p[j]]==0)continue; if(pos[p[j]]==1e8)pos[p[j]]=i; else if(mi[i-1]<mi[pos[p[j]]-1]) pos[p[j]]=i; } } return mi[n-1]; } };