1. 程式人生 > >BZOJ4917: [Lydsy1706月賽]Hash Killer IV(模擬)

BZOJ4917: [Lydsy1706月賽]Hash Killer IV(模擬)

4917: [Lydsy1706月賽]Hash Killer IV

Time Limit: 1 Sec  Memory Limit: 256 MB
Submit: 327  Solved: 140
[Submit][Status][Discuss]

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是個一次函式,可以直接乘除法逆運算求回去,x(1+a)=y------>x=y*rev(1+a),由於mod是偶數,1+a是奇數,求個逆元就ok了。

2和4操作可以先固定前面幾位,然後模擬。

#include<bits/stdc++.h>
#define ui unsigned int
using namespace std;
ui get(ui ans,int len){
    ui x=0;
    for(int i=31;i>=31
-len+1;i--) x|=ans&(1u<<i); for(int i=31-len;i>=0;i--) { if(ans&(1u<<i)){ if(!(x&(1u<<(i+len)))) x|=(1u<<i); } else if((x&(1u<<(i+len)))) x|=(1u<<i); } return x; } int main() { int T,x; scanf("%d",&T); while(T--){ scanf("%u",&x); x*=4294901761u; x=get(x,11); x*=954437177u; x=get(x,6); x*=3222273025u; printf("%u\n",x); } return 0; }