CF1257E/F

E

给出三个序列共n个元素,每个元素值为1~n且不重

一次可以把一个元素换到另一个序列中,求最少操作次数使得三个序列(可为空)分别排序后并在一起为1~n顺序

题解

(伪)神仙题

随便dp,依次考虑每个数放在那里

由于要保证最终的顺序,所以放的序列的编号要单调

f[i][0/1/2],第i个放在0/1/2的最小操作数

code

#include 
#include 
#include 
#include 
#include 
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a

F

n个数,求一个x(x<=2^30-1)使得每个ai xor x二进制下一的个数相同

ai<=2^30-1

题解

折半,每边15位

设n个数最终1的个数为x,i的前15位异或后1的个数为ci

那么后15位的个数分别为x-c1,x-c2,x-c3...x-cn

差分一下变成c1-c2,c2-c3,c3-c4...,刚好与前15位的差分c2-c1,c3-c2,c4-c3...成相反数关系

处理出一边的情况,把序列取反哈希后丢到map里,再枚举另一边判断即可

code

#include 
#include 
#include 
#include 
#include 
#include 
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define mod 1145141919810ll
using namespace std;

int a[101];
int b[101];
int n,i,j,k,l,x,s1,s2;
map hs;
map :: iterator I;
long long s;

int get(int x)
{
    int s=0;
    
    while (x)
    {
        ++s;
        x^=x&-x;
    }
    
    return s;
}

int main()
{
//  freopen("f.in","r",stdin);
    
    scanf("%d",&n);
    fo(i,1,n)
    scanf("%d",&a[i]),b[i]=a[i]&32767,a[i]=a[i]>>15;
    
    fo(x,0,32767)
    {
        s=1;
        fo(i,1,n)
        {
            s1=get(a[i]^x);
            
            if (i>1)
            s=(s*233+(s1-s2+233))%mod;
            
            s2=s1;
        }
        
        hs.insert(map::value_type(s,x));
    }
    
    fo(x,0,32767)
    {
        s=1;
        fo(i,1,n)
        {
            s1=get(b[i]^x);
            
            if (i>1)
            s=(s*233+(s2-s1+233))%mod;
            
            s2=s1;
        }
        
        I=hs.find(s);
        if (I!=hs.end())
        {
            printf("%d\n",(*I).second*32768+x);
            return 0;
        }
    }
    
    printf("-1\n");
}

你可能感兴趣的:(CF1257E/F)