zoukankan      html  css  js  c++  java
  • [Noi2016十连测第五场]二进制的世界

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <algorithm>
     6 using namespace std;
     7 #define maxn 100005
     8 #define maxk 256
     9 int n,type,ans,sum,a[maxn],f[maxk][maxk],g[maxk][maxk];
    10 bool v[maxk];
    11 char st[5];
    12 void read(int &x){
    13     x=0; int f=1; char ch;
    14     for (ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') f=-1;
    15     for (;isdigit(ch);ch=getchar()) x=x*10+ch-'0'; x*=f;
    16 }
    17 int hs(int x,int y){
    18     if (st[1]=='o') return x|y;
    19     if (st[1]=='a') return x&y;
    20     if (st[1]=='x') return x^y;
    21 }
    22 int main(){
    23     read(n),scanf("%s",st+1),read(type);
    24     for (int i=1;i<=n;i++) read(a[i]);
    25     for (int i=1;i<=n;i++){
    26         int k=a[i]&255;
    27         if (i>1){
    28             sum=ans=0;
    29             for (int j=0;j<256;j++){
    30                 if (g[j][k]==0) continue;
    31                 if ((f[j][k]|(hs(j,a[i]>>8)<<8))==ans) sum+=g[j][k];
    32                 if ((f[j][k]|(hs(j,a[i]>>8)<<8))>ans) ans=f[j][k]|(hs(j,a[i]>>8)<<8),sum=g[j][k];
    33             }
    34             if (type==1) printf("%d %d
    ",ans,sum);
    35             else printf("%d
    ",ans);
    36         }
    37         for (int j=0;j<256;j++){
    38             if (f[a[i]>>8][j]==hs(j,k)) g[a[i]>>8][j]++;
    39             if (f[a[i]>>8][j]<hs(j,k)) f[a[i]>>8][j]=hs(k,j),g[a[i]>>8][j]=1;
    40         }
    41     }
    42     return 0;
    43 }
    View Code

    题目链接:http://begin.lydsy.com/JudgeOnline/problem.php?id=3014。

    题目大意:给定一种运算,为or,ans,xor中的一种,以及一个长度为n的序列,第i个数为ai,我们设第i个人与第j个人的友好度为ai与aj位运算,这种位运算是题目给定的,求第2个人到第n个人与其左边的人友好程度的最大值及达到该最大值的方案数。n<=100000;ai<=2^16;

    做法:如果考虑暴力做,因为ai小于等于2^16,所以暴力做可以做到加入O1,而查询O(2^16),显然是不可以的,然而O(2^8*n)是可以过此题的,根据莫队算法的思想,我可以平衡这种暴力,使得两种操作都达到根号n的复杂度。

    正解:我们考虑DP,设f[i][j]表示前8位为i,后8位为j位运算后使得后8位的最大值及方案数,怎么做呢,我们在加入一个数时,我们枚举j,设该数前8位为a,后8位为b,我们用j~b(~表示位运算)来更新f[a][j],查询时,设该数前8位为a,后8位为b,我们可以枚举i用f[i][b]|((i~a)<<8)更新答案即可,复杂度为O(2^8*n)。

    dp。

  • 相关阅读:
    java多线程编程(一基础概念)
    【转】android程序编译过程
    【转】什么是线程安全和线程不安全
    【转】计算机中时间的表示和存储
    【转】字符编码
    C/C++程序编译流程
    NDK学习笔记-JNI的异常处理与缓存策略
    NDK学习笔记-JNI数据类型和属性方法的访问
    NDK学习笔记-JNI数据类型和属性方法的访问
    NDK学习笔记-JNI开发流程
  • 原文地址:https://www.cnblogs.com/OYzx/p/5607460.html
Copyright © 2011-2022 走看看