zoukankan      html  css  js  c++  java
  • 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]<<" ";
    }
    
  • 相关阅读:
    js使用html2canvas实现页面截图并保存图片
    微信小程序之图片base64解码
    微信小程序之回调函数
    小程序横向滚动
    搭建vue开发环境的步骤
    检测算法简介及其原理——fast R-CNN,faster R-CNN,YOLO,SSD,YOLOv2,YOLOv3
    hadoop常用命令
    工作流调度系统Azkaban的简介和使用
    java微服务简介与实战
    mxnet快速入门教程
  • 原文地址:https://www.cnblogs.com/iss-ue/p/12809583.html
Copyright © 2011-2022 走看看