Codeforces.GYM101612E.Equal Numbers(貪心)
阿新 • • 發佈:2018-10-27
register http 數列 0kb max turn mes etc tor
題目鏈接
\(Description\)
給定\(n\)個數,每次可以將任意一個數乘上任意一個正整數。
求\(k\)次操作後,數列中數的種類最少可以是多少。對每個\(0\leq k\leq n\)輸出答案。
\(n\leq 3\times10^5,a_i\leq10^6\)。
\(Solution\)
有兩種貪心策略,一是每次找一個出現次數最少的數,把它變成所有數的LCM;二是找一個出現次數最少,且它的某個倍數存在於原數列裏的數,將它變成它的這個倍數。
對兩種情況取\(\min\)即可。
//93ms 8600KB #include <cstdio> #include <cctype> #include <vector> #include <algorithm> //#define gc() getchar() #define MAXIN 300000 #define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++) typedef long long LL; const int N=1e6+3; int tm[N]; std::vector<int> va,vb; char IN[MAXIN],*SS=IN,*TT=IN; inline int read() { int now=0;register char c=gc(); for(;!isdigit(c);c=gc()); for(;isdigit(c);now=now*10+c-'0',c=gc()); return now; } int main() { freopen("equal.in","r",stdin); freopen("equal.out","w",stdout); int n=read(); for(int i=1; i<=n; ++i) ++tm[read()]; for(int i=1; i<N; ++i) if(tm[i]) { va.push_back(tm[i]);//只關心次數 for(int j=i+i; j<N; j+=i) if(tm[j]) {vb.push_back(tm[i]); break;} } std::sort(va.begin(),va.end()); std::sort(vb.begin(),vb.end()); int tmp=va.size(); va.push_back(1e8), vb.push_back(1e8); std::vector<int>::iterator pa=va.begin(),pb=vb.begin(); for(int i=0,sa=0,sb=0,a=0,b=0; i<=n; ++i) { while(sa+*pa<=i) sa+=*pa++, ++a; while(sb+*pb<=i) sb+=*pb++, ++b; printf("%d ",tmp-std::max(a-1,b)); } return 0; }
Codeforces.GYM101612E.Equal Numbers(貪心)