hihoCoder挑战赛37(暂时只有A题)

官方解法链接

 

目录

官方解法链接

题目1 : XOR

题意分析:

1.题是什么?

2.思路

(1).官方思路

(2).我的思路

3.ac代码

(1).官方解法

(2).我的解法

题目2 : GCD

题意分析

1.题是什么?

2.思路


题目1 : XOR

时间限制:10000ms

单点时限:1000ms

内存限制:512MB

描述

给定非负整数x, k。请计算有多少个非负整数y满足y + (x xor y) = x + k。其中+表示普通的整数加法,xor表示按位异或。如果有无穷个这样的y,则输出-1。

输入

输入一行包含两个整数x, k。 (0 ≤ x, k ≤ 109)

输出

输出一行答案。

样例解释

y = 12, 13, 14, 15

样例输入

3 24

样例输出

4

题意分析:

1.题是什么?

  给你x,k,问你满足y + (x xor y) = x + k的y有多少个,其实不存在无穷多个的情况,可以推理得知.

2.思路

(1).官方思路

    k是奇数则无解,如果(k/2)&x!=0也无解, 令popcount为x的二进制中1的个数,2^{poopcount}即是答案......

(2).我的思路

    从位上下手,x,k小于十亿,分析算式得知y也必然小于二十亿,故而其实就是要确定y这32个二进制位每个二进制位是0还是1,而且由于算式的特殊性,x,k必须要给的合理才会存在答案,一道奇怪的题.

                                                  记住式子是y + (x xor y) = x + k

    我们从2^{0}位开始判断,4*2只有8种情况

        1.假设x的2^{0}位为1,x+k的2^{0}位为0        

             假如y的2^{0}位为1,只看这一位,1+1异或1 结果为1,不满足x+k的0,必然无解

             假如y的2^{0}位为0,只看这一位,0+1异或0 结果为1,不满足x+k的0,必然无解

         2.假设x的2^{0}位为0,x+k的2^{0}位为1,

             假如y的2^{0}位为1,只看这一位,1+0异或1 结果为0,不满足x+k的1,必然无解

             假如y的2^{0}位为0,只看这一位,0+0异或0 结果为0,不满足x+k的1,必然无解

         3.假设x的2^{0}位为1,x+k的2^{0}位为1,

             假如y的2^{0}位为1,只看这一位,1+1异或1 结果为1,满足x+k的1,无进位

             假如y的2^{0}位为0,只看这一位,0+0异或1 结果为1,满足x+k的1,无进位

        4.假设x的2^{0}位为0,x+k的2^{0}位为0,

             假如y的2^{0}位为1,只看这一位,1+0异或1 结果为0,满足x+k的0,进位1,此时x+k自然该减去进上来的这部分再递归(非常重要)

             假如y的2^{0}​​​​​​​位为0,只看这一位,0+0异或0 结果为0,满足x+k的0,无进位

上面的肯定看了晕,不过跟着想一想所有情况,想想就懂了,dfs判断完这32位就好,理论上疑似存在爆栈风险,不过实际代码ac了.

3.ac代码

(1).官方解法

#include <stdio.h>

void solve(){
	int x,k;
	scanf("%d%d",&x,&k);
	if(k%2||((k/2)&x)) printf("0\n");
	else{
		int ans=1;
		while(x){
			if(x&1) ans<<=1;
			x>>=1;
		}
		printf("%d\n",ans);
	}
}


int main(){
	solve();
	return 0;
}

(2).我的解法

#include <stdio.h>

int ans=0;
void dfs(int x,int xk,int power){//x是此时的x,xk是此时的x+k,power是此时的倍数
	if(!x&&!xk){ //当两个都为0,就可以收尾此支线了,y剩下的二进制必取0
		ans+=power;
		return;	
	}
	if((x&1)==1&&(xk&1)==1){
		dfs(x>>1,xk>>1,power<<1);
	}
	else if((x&1)==0&&(xk&1)==0){
		dfs(x>>1,xk>>1,power);
		xk-=2; //很重要,对第7种情况产生的进位影响的抵消.
		dfs(x>>1,xk>>1,power);
	}
}


void solve(){
	int x,k;
	scanf("%d%d",&x,&k);
	dfs(x,x+k,1);
	printf("%d\n",ans);
}


int main(){
	solve();
	return 0;
}

题目2 : GCD

时间限制:5000ms

单点时限:1000ms

内存限制:512MB

描述

给定一个{1, 2, ..., n}的排列a[1], a[2], ..., a[n]。请问有多少对整数(i, j)满足1 ≤ i ≤ j ≤ n,且gcd(i, j) = gcd(a[i], a[j]) = 1。这里gcd表示最大公约数。

输入

第一行包含一个整数n。 (1 ≤ n ≤ 200000)

第二行包含空格隔开的n个整数a[1], a[2], ..., a[n],保证是一个排列。

输出

输出一行答案。

样例输入

6
1 6 2 5 3 4

样例输出

10

题意分析

1.题是什么?

  给你一个大小n的数字序列,由打乱的1到n构成,问你任取1 ≤ i ≤ j ≤ n,gcd(i, j) = gcd(a[i], a[j]) = 1的方案有多少种?

2.思路

 一道数论的题,看到这题我就知道我栽了,也别ac代码了,我理解一下公式先

    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值