Codeforces-959D Mahmoud and Ehab and another array construction task 素數篩+質因數分解
阿新 • • 發佈:2019-01-29
題意:
給一個數組a,求大於或者等於陣列a的字典序的陣列b,其中b滿足陣列內任意數互質,bi>=2。並且是所有滿足條件中的字典序最小的一個。
題解:
這道構造題首先要考慮的就是如果a陣列內的數互質的話,就不需要構造出b陣列,直接輸出a陣列就可以了。那麼我們怎麼判斷整個陣列內的數是否互質呢?不能單單的左右判斷就完事(意思就是假如,2,3,4判斷是否互質,2和3不互質,3和4不互質,那麼不互質,結果是錯誤的)。我們可以考慮對每個數質因數分解。如果出現有重複的就要從這個數開始構造。找到第一個比這個數大而且與前面的數互質的數,然後從小到大輸出不重複的素數就可以了。這道題還有個坑點。。就是素數表的範圍不要只打到1e5個,因為答案要的最大素數可能不在1e5個數內。另外需要的就是質因數分解的時候要先判斷這個數的全部質因數是否有重複,再存放重複,不然的話就會出錯,比如3個數據3,6,2。
#include<stdio.h> #include<string.h> #include<math.h> #include<vector> #include<set> #include<algorithm> using namespace std; const int MAXN=2e6+7; int a[MAXN],b[MAXN]; bool prime[MAXN],c[MAXN]; int cnt; void prim() { int i, j; prime[0]=prime[1]=0,prime[2]=1; for(i=3; i<MAXN; i++){ if(i%2) prime[i]=1; else prime[i]=0;//偶數都不為素數。 } for(i=3; i<=sqrt(MAXN); i++) { if(prime[i]==1) for(j=i+i; j<MAXN; j+=i)//選出素數的倍數(因為素數的倍數能被整除,所以不是素數。) prime[j]=0; } cnt=0; // for(i=2; i<1e7; i++) // if( prime[i]==1 )printf("%d %d\n",i,++cnt); // printf("\n"); for(int i=2;i<MAXN;i++) { if(prime[i]==1) b[++cnt]=i; // if(cnt>1e5)//這個條件是錯誤的,因為最後要輸出的最大的素數有可能不會出現在這1e5個素數內。因為這個點WA了一整天,靠。。。 // break; } } bool check(int x) { int temp=x; for(int i=2;i*i<=temp;i++) { if(temp%i==0) { if(c[i]) return 0; while(temp%i==0) temp/=i; } } if(temp>1) { if(c[temp]) return 0; } for(int i=2;i*i<=x;i++) { if(x%i==0) { c[i]=1; while(x%i==0) x/=i; } } if(x>1) c[x]=1; return 1; } int main() { int n; prim(); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); bool flag=false; int j; for(int i=1;i<=n;i++) { j=i; if(check(a[i])) printf("%d ",a[i]),c[a[i]]=1; else{ flag=true; break; } } if(flag){ for(int k=a[j];k<=1e7&&j<=n;k++) { if(check(k)){ printf("%d ",k),c[k]=1,j++; break; } } for(int k=1;k<=cnt&&j<=n;k++) { if(!c[b[k]]){ printf("%d ",b[k]); j++; c[b[k]]; } } printf("\n"); } }