zoukankan      html  css  js  c++  java
  • 终章剑之魂【模拟】【贪心】

    题目大意:

    给出n个数,输出他们其中两个数进行与运算后的最大值。
    Input

    5
    12 5 6 3 1

    Output

    4

    思路:

    这道题比较简单,特别是40分的部分。直接O(n2)两两枚举,记录进行与运算后的最大值即可。

    #include <cstdio>
    #include <iostream>
    using namespace std;
    
    int n,a[10001],ans,maxn;
    
    int main()
    {
        freopen("sword.in","r",stdin);
        freopen("sword.out","w",stdout);
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
         scanf("%d",&a[i]);
        for (int i=1;i<n;i++)
         for  (int j=i+1;j<=n;j++)  //枚举
          if (i!=j) ans=max(ans,a[i]&a[j]);  
        return printf("%d\n",ans)&0;
    } 

    这道题100分就有点难拿了。我们必须在O(n)O(nlongn)的时间复杂度内完成。所以很容易想到贪心。这题贪心 由于数据水 是可以过的。但是如果遇到下面这种情况就WA了。
    Input

    3
    13 10 9

    Output

    9
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int n,a[1000001],ans=-1;
    bool cmp(int x,int y) {return x>y;}
    int main()
    {
        freopen("sword.in","r",stdin);
        freopen("sword.out","w",stdout);
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        sort(a+1,a+n+1,cmp);  //从大到小排序
        for (int i=1;i<=n;i++)
        {
            if ((a[i]&a[i+1])<=ans) break;
            ans=a[i]&a[i+1];  //贪心,每次将相邻的两个数字进行与运算
        }
        printf("%d",ans);
    }

    这道题还有另一种AC方法,不过是O(n2)优化,如果数据坑一点就TLE了。

    #include<cstdio>
    #include<algorithm>
    using namespace std; 
    int n,answ,a[1000005]; 
    
    bool cmp(int x,int y) 
    { 
        return x>y;
    }
    
    int main()
    {
        scanf("%d",&n); 
        for (int i=1;i<=n;i++)
         scanf("%d",&a[i]); 
         sort(a+1,a+n+1,cmp); 
        for (int i=1;i<n;i++)
        if (a[i]>answ){  //剪枝
         for (int j=i+1;j<=n;j++)
          if ((a[i]&a[j])>=answ) answ=(a[i]&a[j]);          
        }
         printf("%d",answ); 
    }

    正解:

    枚举输入数字最大值的log2后的结果,再枚举一次每个数,将与最大值的第i位的数字不相同的都删除(为了保证答案最大),剩余两个数即为答案。
    时间复杂度:O(n)


    代码:

    #include <cstdio>
    #include <iostream>
    #define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
    using namespace std;
    
    int n,a[2000001],sum,o,ans;
    
    int main()
    {
        fre(sword);
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
         scanf("%d",&a[i]);
        for (int i=30;i>=0;i--)  //枚举,log之后最多不会超过30位。
        {
            sum=0;
            o=1<<i;  //2^i
            for (int j=1;j<=n;j++)
             if ((a[j]&ans)==ans&&(a[j]&o)==o)  //符合要求
              sum++;
            if (sum>1) ans+=o;  //能匹配
        }
        return printf("%d\n",ans)&0;
    }
  • 相关阅读:
    日期和时间模块
    批处理bat文件dos命令实现文件的解压缩
    批处理bat文件dos命令复制文件
    dos命令临时和永久设置环境变量方法
    [转]NHibernate之旅(13):初探立即加载机制
    [转]NHibernate之旅(12):初探延迟加载机制
    [转]NHibernate之旅(11):探索多对多关系及其关联查询
    [转]NHibernate之旅(10):探索父子(一对多)关联查询
    [转]NHibernate之旅(9):探索父子关系(一对多关系)
    [转]NHibernate之旅(8):巧用组件之依赖对象
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/9313032.html
Copyright © 2011-2022 走看看