1. 程式人生 > >【BZOJ4917】Hash Killer IV 亂搞

【BZOJ4917】Hash Killer IV 亂搞

input inline 數據 line ans style %d bsp zoj

【BZOJ4917】Hash Killer IV

Description

有一天,tangjz造了一個Hash函數: unsigned int Hash(unsigned int v){ unsigned int t = v; t = t + (t << 10); t = t ^ (t >> 6); t = t + (t << 3); t = t ^ (t >> 11); t = t + (t << 16); return t; } 小Q發現這個函數非常不靠譜,對於任意的t,他可以隨手構出個數字v使得Hash(v)=t。 小Q現在想考考你,他將給出Q個t,你需要構造出滿足條件的v。

Input

第一行包含一個正整數Q(1<=Q<=100000),表示詢問的個數。 接下來Q行,每行一個整數t(0<=t<2^32),表示詢問的t。 輸入數據保證對於每個t至少存在一組解。

Output

對於每組數據輸出一行一個整數,即合法的v,若有多組可行解,輸出任意一組。

Sample Input

4
614278301
1228622139
1841720774
2457244278

Sample Output

1
2
3
4

題解:發現每個操作都是能反過來的。對於操作1,3,5,可以看成是原數*一個數,因為乘的是奇數而模數是偶數,所以反過來做的話直接乘逆元就行了。對於2,4操作,首先最高的6/11位是不受影響的,然後依次確定後面的位即可。

#include <cstdio>
typedef unsigned int ui;
ui ans,x;
inline ui work(ui x,int y)
{
	for(int i=31-y;i>=0;i--)	x^=((x&(1u<<(i+y)))>>y);
	return x;
}
int main()
{
	int T;	scanf("%d",&T);
	while(T--)	scanf("%u",&ans),ans*=4294901761u,ans=work(ans,11),ans*=954437177u,ans=work(ans,6),ans*=3222273025u,printf("%u\n",ans);
	return 0;
}

【BZOJ4917】Hash Killer IV 亂搞