zoukankan      html  css  js  c++  java
  • 【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]
    */

      

      

  • 相关阅读:
    C#设计模式之策略模式
    c#设计模式之单例模式
    关于分布式事务的实现梳理
    sql事务的使用及其技巧整理
    关于web系统整体优化提速总结
    .net导出excle无需任何插件,直接通过一个tablehtml实现
    ajax+ashx:实现文件的批量导出
    angularjs学习第九天笔记(指令作用域【隔离作用域】研究)
    angularjs学习第八天笔记(指令作用域研究)
    angularjs小练习(分别通过ng-repeat和ng-option动态生成select下拉框)
  • 原文地址:https://www.cnblogs.com/flipped/p/6071541.html
Copyright © 2011-2022 走看看