【USACO 3.1】Humble Numbers(给定质因子组成的第n大的数)

题意:给你k(≤100)个质数,求质因子只包含它们的第n大的数。

题解:

方法一:维护一个数组,一开始只有给出的质数在里面,用每个质数去乘以数组中每个数,然后归并排序,长度保留到n,一轮接一轮,直到乘出来的新出现的数大于原来最大的数,那么如果当前是用最小的质数都没产生新的前n大的数,那么第n个数就是第n大的数。否则跳转到用最小的质数去乘。具体见代码。

/*
TASK: humble
LANG: C++
*/
#include<cstdio>
#include<algorithm>
#include<iostream>
#define N 100005
#define ll long long
using namespace std;
int n,k,p[N];
ll a[N],b[N],c[N];
bool merge(ll a[],ll b[]){
    bool f=0;
    for(int k=1,i=1,j=1;k<=n;k++)
        if(!b[j]||a[i]&&a[i]<=b[j]){
            c[k]=a[i];
            if(a[i]==b[j])j++;
            i++;
        }else{
            f=1;
            c[k]=b[j];
            j++;
        }
    for(int i=1;i<=n&&c[i];i++)a[i]=c[i];
    return f;
}
ll solve(){
    while(1){
        for(int i=1;i<=k;i++){
            for(int j=1;j<=n;j++){
                a[j]=p[i]*b[j];
                if(b[j]==0||b[n]&&a[j]>b[n])break;
            }
            if(!merge(b,a)){
                if(i==1)return b[n];
                else i=0;
            }
        }
    }
}
int main(){
    freopen("humble.in","r",stdin);
    freopen("humble.out","w",stdout);
    scanf("%d%d",&k,&n);
    for(int i=1;i<=k;i++){
        scanf("%d",&p[i]);
        b[i]=p[i];
    }
    printf("%d
",solve());
    return 0;
}

/*
   Test 1: TEST OK [0.000 secs, 6912 KB]
   Test 2: TEST OK [0.000 secs, 6912 KB]
   Test 3: TEST OK [0.000 secs, 6912 KB]
   Test 4: TEST OK [0.011 secs, 6912 KB]
   Test 5: TEST OK [0.043 secs, 6912 KB]
   Test 6: TEST OK [0.151 secs, 6912 KB]
   Test 7: TEST OK [0.032 secs, 6912 KB]
   Test 8: TEST OK [0.032 secs, 6912 KB]
   Test 9: TEST OK [0.000 secs, 6912 KB]
   Test 10: TEST OK [0.000 secs, 6912 KB]
   Test 11: TEST OK [0.000 secs, 6912 KB]
   Test 12: TEST OK [0.205 secs, 6912 KB]
*/
 

方法二:用set,对于每个质数,与set中最小的的乘积插入set,set中维护至多n个元素,然后迭代器后移,直到乘出来的数比最大的数还大或者超出long long就跳出,set中第n个即最大的就是答案。

/*
TASK: humble
LANG: C++
*/
#include<cstdio>
#include<algorithm>
#include<iostream>
#define N 105
#define ll long long
#include<set>
using namespace std;
int n,k,p[N];
set<ll>s;
int main(){
    freopen("humble.in","r",stdin);
    freopen("humble.out","w",stdout);
    cin>>k>>n;
    for(int i=1;i<=k;i++){
        cin>>p[i];
        s.insert(p[i]);
    }
    set<ll>::iterator it;
    for(int i=1;i<=k;i++){
        it=s.begin();
        while(1){
            ll t=*it*p[i];
            if(t<0)break;
            if(s.size()>n){
                s.erase(--s.end());
                if(t>(*--s.end()))break;
            }
            s.insert(t);
            it++;
        }
    }
    cout<<*(--s.end())<<endl;
    return 0;
}
/*
   Test 1: TEST OK [0.000 secs, 4184 KB]
   Test 2: TEST OK [0.000 secs, 4184 KB]
   Test 3: TEST OK [0.000 secs, 4184 KB]
   Test 4: TEST OK [0.011 secs, 4448 KB]
   Test 5: TEST OK [0.032 secs, 4844 KB]
   Test 6: TEST OK [0.151 secs, 7220 KB]
   Test 7: TEST OK [0.043 secs, 5108 KB]
   Test 8: TEST OK [0.032 secs, 4976 KB]
   Test 9: TEST OK [0.000 secs, 4184 KB]
   Test 10: TEST OK [0.000 secs, 4184 KB]
   Test 11: TEST OK [0.000 secs, 4184 KB]
   Test 12: TEST OK [0.216 secs, 7220 KB]

*/

方法三:超时一个点。用优先队列的小根堆即

priority_queue<ll,vector<ll>,greater<ll> >q;

每次用队首乘上每个质数并插入小根堆,并队首出队。第n个出队的就是答案,并且要进行判重,t=q.top()*p[j]; if(ans[i]<t){ans[++i]=t;...}。

 方法四:官方题解,用d[i]记录第i个质数要乘到第几个丑数,每次把每个质数和要乘的丑数的乘积的最小值作为新加的丑数,每个质数要乘的丑数就是满足和它相乘后,比最后一个丑数大的最小的丑数。

/*
TASK: humble
LANG: C++
*/
#include<cstdio>
#include<algorithm>
#include<iostream>
#define N 100005
#define ll long long
using namespace std;
int n,k,p[105];
ll hum[N],d[N];
int main(){
    freopen("humble.in","r",stdin);
    freopen("humble.out","w",stdout);
    scanf("%d%d",&k,&n);
    for(int i=1;i<=k;i++)
        scanf("%d",&p[i]);
    hum[0]=1;
    for(int i=1;i<=n;i++){
        ll m=hum[i-1]*p[1];
        for(int j=1;j<=k;j++){
            while(hum[d[j]]*p[j]<=hum[i-1])d[j]++;
            if(m>hum[d[j]]*p[j])m=hum[d[j]]*p[j];
        }
        hum[i]=m;
    }
    printf("%lld
",hum[n]);
    return 0;
}
/*
Test 1: TEST OK [0.000 secs, 5740 KB]
Test 2: TEST OK [0.000 secs, 5740 KB]
Test 3: TEST OK [0.000 secs, 5740 KB]
Test 4: TEST OK [0.000 secs, 5740 KB]
Test 5: TEST OK [0.000 secs, 5740 KB]
Test 6: TEST OK [0.022 secs, 5740 KB]
Test 7: TEST OK [0.000 secs, 5740 KB]
Test 8: TEST OK [0.000 secs, 5740 KB]
Test 9: TEST OK [0.000 secs, 5740 KB]
Test 10: TEST OK [0.000 secs, 5740 KB]
Test 11: TEST OK [0.000 secs, 5740 KB]
Test 12: TEST OK [0.108 secs, 5740 KB]
*/

  

  

原文地址:https://www.cnblogs.com/flipped/p/6071541.html