1. 程式人生 > >hihoCoder挑戰賽37(暫時只有A題)

hihoCoder挑戰賽37(暫時只有A題)

目錄

題意分析:

2.思路

題意分析

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程式碼了,我理解一下公式先