写在前面

我还是太菜了,考试的时候只写了一个70pts70pts70pts的暴力,用mapmapmap居然可以过707070分。这么良心的出题人少见了啊,然而之后的满分做法会让你们知道出题人有多么毒瘤。

Solution

70pts70pts70pts做法

反正题目都给了你一个Hash函数,直接预处理然后mapmapmap储存就可以搞定。

100pts100pts100pts做法

本题实质上是一个编码与解码的问题,我们只需要对于每个给定的输入,一波逆运算就可以AC。
然而,HashHashHash函数长成这样:

unsigned int Hash(unsigned int t){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;
}

观察以后发现,诶,有个异或操作,woc,我不会还原异或!!!!!
不要慌,仔细想一想,对于t=tt=tt=t ^ (t&gt;&gt;i)(t&gt;&gt;i)(t>>i),我们在计算之前,可以考虑把ttt分成32i32 \over ii32​份(结果向上取整),为什么要这么做呢?因为可以看做是这样的:

按照上面的想法,我们将现在的数分成三份(当前的数按照二进制表示,是一个010101串):X1X1X1,X2X2X2,X3X3X3。
那么X1X1X1可以看作是t&lt;&lt;22t&lt;&lt;22t<<22,那么X2X2X2怎么算呢?我们可以这样想:

这个想法很直观,但是怎么在数学上实现呢?先让t&gt;&gt;11t&gt;&gt;11t>>11,这样就裁掉X3X3X3了,然后我们再让ttt异或上X1&lt;&lt;11X1&lt;&lt;11X1<<11,因为一个数异或自己等于零,异或零等于自己,所以说我们让ttt当中原来和X1X1X1相等的部分和X1&lt;&lt;11X1&lt;&lt;11X1<<11异或,这样就在裁掉X1X1X1的同时,保证了X2X2X2是完好的。X3X3X3按照一样的思想,稍加推算也可以得出式子。
那么,现在我们有X1X1X1,X2X2X2,X3X3X3了,怎么进一步还原ttt呢?注意到,现在的数,实际上是原数异或上X1,X2X1,X2X1,X2两段得到的,也就是说现在的X2X2X2是原数的X2X2X2和现在的X1X1X1异或得到的,所以说反过来异或一次,即X2X2X2异或X1X1X1,就是原数的X2X2X2那一段,X3X3X3同理,X1X1X1是没有变的。所以会所我们再将这几段拼接回去就好了。方法也很简单,将X1&lt;&lt;22X1&lt;&lt;22X1<<22异或X2&lt;&lt;11X2&lt;&lt;11X2<<11再异或X3X3X3即可,可以自己手推一下,加深理解。
这样的话,异或的逆运算就解决了,而加又怎么办呢?
其实这相当解一个方程:
(2i+1)x≡t(mod232) \left(2^i+1\right)x\equiv t \pmod {2^{32}} (2i+1)x≡t(mod232)
显然扩展欧几里得算法就可以搞定这一步,具体见代码实现。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll read(){ll sum=0,neg=1;char c=getchar();while((c>'9'||c<'0')&&c!='-') c=getchar();if(c=='-') neg=-1,c=getchar();while(c>='0'&&c<='9') sum=(sum<<1)+(sum<<3)+c-'0',c=getchar();return sum*neg;
}
/* 70pts做法,十分暴力的打表。
map<unsigned int,int> h;
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;
}
int main(){freopen("encrypt.in","r",stdin);freopen("encrypt.out","w",stdout);for(unsigned int i=1;i<=100000;i++) h[Hash(i)]=i;int q;q=read();for(int i=1;i<=q;i++){int t;t=read();printf("%d\n",h[t]);}return 0;
}
*/
//100pts
const ll mod=1ll<<32;
ll exgcd(ll a,ll b,ll &x,ll &y){b?(exgcd(b,a%b,y,x),y-=a/b*x):(x=1,y=0);
}
ll calcinv(ll t){ll x,y;exgcd(t,mod,x,y);x=(x%mod+mod)%mod;return x;
}
ll ksc(ll a,ll b,ll ret=0){//快速乘,直接乘会爆long long for(;b;b>>=1,a=(a+a)%mod) if(b&1) ret=(ret+a)%mod;return ret;
}
int main(){/*ios::sync_with_stdio(false);cin.tie(NULL); cout.tie(NULL);*/int q;q=read();for(int i=1;i<=q;i++){ll t=read();//第一步还原->还原t=t+(t<<16) t=ksc(t,calcinv((1ll<<16)+1));//第二步还原->还原t=t^(t>>11) ll x1=t>>22,x2=(t>>11)^(x1<<11),x3=t^(x1<<22)^(x2<<11);x2=x2^x1; x3=x3^x2; t=(x1<<22)^(x2<<11)^x3;//第三步还原->还原t=t+(t<<3)t=ksc(t,calcinv((1ll<<3)+1));//第四步还原->还原t=t^(t>>6)x1=t>>30,x2=(t>>24)^(x1<<6),x3=(t>>18)^(x1<<12)^(x2<<6);ll x4=(t>>12)^(x1<<18)^(x2<<12)^(x3<<6),x5=(t>>6)^(x1<<24)^(x2<<18)^(x3<<12)^(x4<<6);ll x6=t^(x1<<30)^(x2<<24)^(x3<<18)^(x4<<12)^(x5<<6);x2^=x1,x3^=x2,x4^=x3,x5^=x4,x6^=x5;t=(x1<<30)^(x2<<24)^(x3<<18)^(x4<<12)^(x5<<6)^x6;//第五步还原->还原t=t+(t<<10)t=ksc(t,calcinv((1ll<<10)+1));printf("%lld\n",t);}return 0;
}

转载于:https://www.cnblogs.com/Neonen/p/9832492.html

NOIP提高模拟-20181019-T1-加密相关推荐

  1. 【NOIP提高模拟】奇洛金卡达

    Description 阿良良木历将要迎来人生(不,是吸血鬼生涯)的第三次战斗--与身为人类的奇洛金卡达在直江津高中的操场solo,以取回Heartunderblade的左右手. 奇洛金卡达.留着刺猬 ...

  2. 【NOIP校内模拟】T1 膜法(组合数)

    整理题意后 对于每个询问其实就是 由于C(m,n)=C(m,m-n) 就变成了 其实就是在杨辉三角上的一列求其中的一段和 然后有个玄学的公式 什么意思呢 证明是很容易得到的 所以把阶乘预处理出来 由于 ...

  3. NOIP提高模拟-20181016-T3-长者

    写在前面 考场上看到本题根本不会,下来以后看了看题解发现是一道主席树+hash的题目,然而完全不会,所以说去认真的学习了主席树之后,成功的A掉了这道题目. Solution 10 p t s 10pt ...

  4. {小结}2016.6.11【初中部 NOIP提高组 】模拟赛C

    2016.6.11[初中部 NOIP提高组 ]模拟赛C No.1!!! 100+33.3+10+90=233.3 23333 1298. 牛棚(graze2.pas/c/cpp) 题解 1299. 洗 ...

  5. 2018.12.08【NOIP提高组】模拟B组总结(未完成)

    2018.12.08[NOIP提高组]模拟B组总结 diyiti 保留道路 进化序列 B diyiti Description 给定n 根直的木棍,要从中选出6 根木棍,满足:能用这6 根木棍拼出一个 ...

  6. 第一届『Citric杯』NOIP提高组模拟赛 题解

    [官方题解]第一届『Citric杯』NOIP提高组模拟赛 题解 第一题 柠檬超市 这题是本次模拟赛的送分题.做法显然. 但是注意此题有一个陷阱: 注意W和C的规模都是10^9,所以如果直接用doubl ...

  7. 2021.01.14【NOIP提高B组】模拟 总结

    2021.01.14[NOIP提高B组]模拟 总结 第一题 Candy 奇奇怪怪的题目. 一开始没有理解题目,其实就是同时变换. 打了一个暴力. 本人随机生成50000组数据,都过了,时间没超.希望出 ...

  8. 2020.08.08【NOIP提高组】模拟:奶牛的图片 总结

    2020.08.08[NOIP提高组]模拟:奶牛的图片 总结 Description Farmer John希望给他的 N ( 1 ≤ N ≤ 100 , 000 ) N(1\leq N\leq100 ...

  9. 5814. 【NOIP提高A组模拟2018.8.14】 树(期望 + 倍增)

    5814. [NOIP提高A组模拟2018.8.14] 树 Problem 给定一棵nnn个点的树,m" role="presentation">mmm次询问,每次 ...

最新文章

  1. 基于web创建逼真的3D图形 | CSS技巧
  2. IQmath中文手册
  3. vmware提示com.vmware.sps.fault.QsConnectionException报错
  4. 看事实风向的网站,做风向建模和出去放风筝,飞无人机的时候可以看一看~
  5. 数据结构栈和队列以及常见算法题
  6. 轻量化版本优于MobileNet系列 | Tokens-to-Token ViT: Training Vision Transformers from Scratch on ImageNet
  7. CSS多行文本溢出省略号...显示设置
  8. ccf矩阵java_CCF系列之矩阵(201512-5)
  9. 数据库改名系列(数据库名,逻辑名,物理文件名)
  10. abb限位开关已打开drv1_ABB机器人常见故障处理
  11. windows 2008 server R2 服务器docker安装
  12. cout与cerr区别
  13. java网页作业提交_基于JAVA网上作业提交批改系统的设计(SQL)(含录像)
  14. 【老九学堂】【初识C语言】常用字符串函数
  15. 领英销售账号的优点和销售账号(专业版)的基本操作,置顶推荐
  16. 域控服务器的dns配置,如何配置额外域控制器上的DNS?
  17. 版本动态 | Apache Linkis(Incubating) 计算中间件1.1.2 版本发布
  18. 网络字节顺序和主机字节顺序的转换(htons ntohs htonl ntohl)
  19. 数据分析思维九段路线图
  20. 嵌入式开发:McObject eXtremeDB嵌入式数据库系统

热门文章

  1. ngui 输入事件处理
  2. Java 7之基础 - 强引用、弱引用、软引用、虚引用
  3. git创建与管理远程分支
  4. WebSocket FlashSocket
  5. 喝清凉茶,吃绿豆汤看绿色奥运[我写绿色IT]
  6. 2008年IT业界10大预言 [转]
  7. zongzi tutorial
  8. 针对firefox ie6 ie7的css样式
  9. 蓝桥杯九宫重排(bfs+用set去重)
  10. oracle使用存储过程做铺底数据