zoukankan      html  css  js  c++  java
  • Codeforces 912E

    912E - Prime Gift

    思路:

    折半枚举+二分check

    将素数分成两个集合(最好按奇偶位置来,保证两集合个数相近),这样每个集合枚举出来的小于1e18的积个数小于1e6。

    然后二分答案,check时枚举其中一个集合,然后找到另外一个集合小于mid/该元素的元素有多少个,这里用到一个双指针的技巧将复杂度降到O(n):一个集合从大到小枚举,那么mid/该元素就会逐渐变大,那么直接从上次找到的位置往后找就可以了,因为答案肯定在后面。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    
    const ll INF=1e18;
    vector<ll>s[2];
    int p[20],a[20];
    ll k;
    void dfs(int l,int r,ll v,int id){
        s[id].pb(v);
        for(int i=l;i<=r;i++){
            if(INF/v>=p[i])dfs(i,r,v*p[i],id);
        }
    }
    bool check(ll a){
        ll cnt=0;
        int j=0;
        for(int i=s[0].size()-1;i>=0;i--){
            while(j<s[1].size()&&a/s[0][i]>=s[1][j])j++;
            cnt+=j;
        }
        return cnt<k;
    }
    int main(){
        ios::sync_with_stdio(false);
        cin.tie(0);
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)cin>>a[i];
        for(int i=1;i<=n/2;i++)p[i]=a[i*2];
        for(int i=n/2+1;i<=n;i++)p[i]=a[(i-n/2)*2-1];
        cin>>k;
        int hf=n/2;
        int _hf=n-hf;
        dfs(1,hf,1,0);
        dfs(hf+1,n,1,1);
        sort(s[0].begin(),s[0].end());
        sort(s[1].begin(),s[1].end());
        ll l=1,r=1e18,mid=(l+r)>>1;
        while(l<r){
            if(check(mid))l=mid+1;
            else r=mid;
            mid=(l+r)>>1;
            //cout<<l<<' '<<r<<endl;
        }
        cout<<mid<<endl;
        return 0;
    }
  • 相关阅读:
    sqlserver监控体系
    使SQL用户只能看到自己拥有权限的库
    存储过程版本控制-DDL触发器
    查看剩余执行时间
    迁移数据库文件位置
    sublime使用Package Control不能正常使用的解决办法
    未在本地计算机上注册“Microsoft.Jet.OLEDB.4.0”提供程序的处理方式
    1770Special Experiment
    1848Tree
    1322Chocolate
  • 原文地址:https://www.cnblogs.com/widsom/p/8352859.html
Copyright © 2011-2022 走看看