• D. Ehab the Xorcist(纯构造方法)


    (如果觉得下面难以理解,可以去这里看一种较为简单的解法):saf

    (这个题嘛,首先要明确异或的性质:相同为0,不同为1.)

    (举个例子,我们来构造u=15和v=127的情况)

    (注意到,异或是二进制,我们把15的二进制写下来)

    [1111 ]

    (color{Red}{说明什么?说明至少二进制的1,2,3,4位数字出现了奇数次,二进制的其他位出现了偶数次。})

    (你问我为什么?请看异或的定义,假如出现偶数次1相异或,仍然为0.)

    (那么我们可以构造出最终数列中,二进制的某一位出现过多少次1.)

    (基于贪心的思想,我们从二进制的62位开始构造。用当前的v整除{2^i})

    (如果在15中出现过这一位,说明我们想构造奇数次,假如除数是偶数就-1)

    (如果在15没出现过,说明我们想构造偶数次,假如是奇数就-1)

    (然后每一次都v都减去构造的数字)

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    ll u,v,a[64],vis[64],ans[109],num[109],cnt,xu;
    bool work()
    {
    	ll minn=1e18,shu=0;
    	for(int i=1;i<=62;i++)
    		if(vis[i])
    		minn=min(minn,vis[i]);//找出出现次数最少的 
    	if(minn==1e18)	return false;//已经可以输出了 
    	for(int i=1;i<=62;i++)
    	{
    		if(vis[i]==0)	continue;
    		vis[i]-=minn,shu+=a[i];//都加上去 
    	}
    	ans[++cnt]=shu,num[cnt]=minn,xu+=minn;
    	return  true;
    }
    int main()
    {
    	a[1]=1;
    	for(int i=2;i<=62;i++)	a[i]=a[i-1]*2;//二进制的额每一位代表的数 
    	cin>>u>>v;
    	for(int i=1;i<=62;i++)
    	if(u&a[i])//标记是否在u出现过 
    	{
    		vis[i]=1;//出现过那么至少要有一次 
    		v-=a[i];
    	}
    	if(v<0)	cout<<-1,exit(0);
    	for(int i=62;i>=1;i--)
    	{
    		ll z=v/a[i];
    		if(z==0)	continue;
    		if(z%2==1&&vis[i])	z--;//出现过应该构造奇数 
    		if(z%2==1&&!vis[i]) z--;//没出现过应该构造偶数 
    		vis[i]+=z;
    		v-=a[i]*z;
    	}
    	if(v!=0)	cout<<-1,exit(0);
    	while(work())	continue;//贪心构成数字 
    	cout<<xu<<endl;
    	for(int i=1;i<=cnt;i++)
    	for(int j=1;j<=num[i];j++)
    		cout<<ans[i]<<" ";
    }
    
  • 相关阅读:
    php_sphinx安装使用
    获取数据库中所有表名
    总结thinkphp快捷查询getBy、getField、getFieldBy用法及场景
    打印机复印身份证方法
    svn 删除、移动和改名
    MySQL中REGEXP正则表达式使用大全
    高铁在高速运行时的电力是如何提供的?
    2016亚洲大学排名
    Mac下安装HBase及详解
    HBase Mac OSX 安装笔记
  • 原文地址:https://www.cnblogs.com/iss-ue/p/12809583.html
Copyright © 2020-2023  润新知