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]<<" ";
    }
    
  • 相关阅读:
    超详细的FreeRTOS移植全教程——基于srm32
    继续学习freertos消息队列
    FreeRTOS优化与错误排查方法
    从单片机到操作系统⑦——深入了解FreeRTOS的延时机制
    Android Pie 私人 DNS 使用教程
    「运维之美」技术周刊 ( 第 1 期 )
    「运维之美」技术周刊 ( 第 3 期 )
    用 Python 快速实现 HTTP 和 FTP 服务器
    关于ubuntu软件图标的问题
    You're currently running Fcitx with GUI 错误解决 Fcitx
  • 原文地址:https://www.cnblogs.com/iss-ue/p/12809583.html
Copyright © 2011-2022 走看看