zoukankan      html  css  js  c++  java
  • Codeforces 979D (STL set)(不用Trie简单AC)

    题面:

    传送门
    题目大意:
    给定一个空集合,有两种操作:
    一种是往集合中插入一个元素x,一种是给三个数x,k,s,问集合中是否存在v,使得gcd(x,v)%k==0,且x+v<=s若存在多个满足条件,则输出使得v⊕x最大的v。

    分析:

    首先,gcd(x,v)%k==0,由数论知识得该条件等价于x%k==0&&v%k==0
    那么,我们怎么快速求出能整除k的v呢
    对操作1输入的数x的每个因数,我们建立一个集合
    s[i]存储能被i整除的所有x
    且由于c++ STL的set的特性,集合内元素从小到大排列,我们可以快速求出x+v<=s的所有v,再从这些值中选出v⊕x最大的v即可

    易错细节
    1.在set中查找时我们要记得判断集合是否为空
    2.注意upper_bound的返回值
    3.集合中只有第一个数满足条件时的特判
    因为我们是这样倒序遍历集合的 for(;it!=s[k].begin();it--)
    所以当集合中只有第一个数满足条件时,it=s[k].begin(),会直接跳出循环
    在循环结尾做一下特判就可以了

    时间复杂度分析:
    操作1时间复杂度O(nlog2n)
    操作2时间复杂度 O(log2n

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<set> 
    #include<cmath>
    #define maxn 100005
    using namespace std;
    set<int>s[maxn]; 
    int n;
    void div(int x){//分解因数,并将x插入每个因数对应的集合
        int sq=(int)sqrt(x);
        for(int i=1;i<=sq;i++){
            if(x%i==0){
                s[i].insert(x);
                s[x/i].insert(x);
            }
        }
    }
    int get_ans(int x,int k,int maxs){
        if(x%k!=0) return -1;
        set<int>::iterator it;
        if(s[k].empty()) return -1;//集合为空的特判
        it=s[k].upper_bound(maxs-x);//查找x+v<=s的最大v (准确的说,是v的下标+1,因为upper_bound的返回值)
        if(it==s[k].begin()) return -1;
        it--;//由上知要-1
        int ans=-1,sum=-1;
        for(;it!=s[k].begin();it--){//从大到小找v⊕x最大的v
            int v=*it;
            if(sum>x+v) break;//因为v⊕x<=v+x
            if(sum<(x^v)){
                ans=v;
                sum=x^v;
            }
        }
        if(sum<(x^*it)) ans=*it;//只有第一个数满足条件时的特判
        return ans;
    }
    int main(){
        int cmd,x,k,s;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&cmd);
            if(cmd==1){
                scanf("%d",&x); 
                div(x);
            }else{
                scanf("%d %d %d",&x,&k,&s);
                printf("%d
    ",get_ans(x,k,s));
            }
        }
    }
  • 相关阅读:
    将dp转为px
    No tracked branch configured for branch dev or the branch doesn't exist. To make your branch track a remote branch call, for example, git branch --set-upstream-to=origin/dev dev
    ConstraintLayout中的chainstyle & guideline >
    android studio中的preview按钮不显示
    EditTextView:取消焦点&自动获取焦点
    HeadFrist 观察者模式(Kotlin版)
    ArrayList排序sort
    时间转换
    kotlin 程序入口
    网络数据请求
  • 原文地址:https://www.cnblogs.com/birchtree/p/9845837.html
Copyright © 2011-2022 走看看