zoukankan      html  css  js  c++  java
  • 【bzoj4917】Hash Killer IV 乱搞

    题目描述

    已知函数:
    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;
    }
    的返回值为t,求传入的参数v。

    输入

    第一行包含一个正整数Q(1<=Q<=100000),表示询问的个数。
    接下来Q行,每行一个整数t(0<=t<2^32),表示询问的t。
    输入数据保证对于每个t至少存在一组解。

    输出

    对于每组数据输出一行一个整数,即合法的v,若有多组可行解,输出任意一组。

    样例输入

    4
    614278301
    1228622139
    1841720774
    2457244278

    样例输出

    1
    2
    3
    4


    题解

    乱搞

    考虑到函数中的五个操作都是可逆的:

    $kv=t$可以直接用欧拉定理$a^{varphi(p)}mod p=1$求出$k$的逆元,乘上$t$即可得到$v$。

    $v^(v>>k)=t$中由于$v>>k$的前$k$位都是$0$,因此$v$的前$k$位就是$t$的前$k$位,然后异或上$t$的$k+1...2k$位可以计算出v的第$k+1...2k$位,以此类推。

    于是倒过来乱搞即可。

    然后卡卡常数就rank 1了好开心(代码中未加入相关优化)

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

     

  • 相关阅读:
    地铁开发进度1
    人月神话阅读笔记二
    学习进度五
    人月神话阅读笔记一
    WebView的用法:
    图框联动
    阅读笔记《人月神话》一
    5
    4
    3
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/7570711.html
Copyright © 2011-2022 走看看