日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

NOIP提高模拟-20181019-T1-加密

發(fā)布時(shí)間:2025/3/16 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 NOIP提高模拟-20181019-T1-加密 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

寫在前面

我還是太菜了,考試的時(shí)候只寫了一個(gè)70pts70pts70pts的暴力,用mapmapmap居然可以過707070分。這么良心的出題人少見了啊,然而之后的滿分做法會(huì)讓你們知道出題人有多么毒瘤。

Solution

70pts70pts70pts做法

反正題目都給了你一個(gè)Hash函數(shù),直接預(yù)處理然后mapmapmap儲(chǔ)存就可以搞定。

100pts100pts100pts做法

本題實(shí)質(zhì)上是一個(gè)編碼與解碼的問題,我們只需要對于每個(gè)給定的輸入,一波逆運(yùn)算就可以AC。
然而,HashHashHash函數(shù)長成這樣:

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; }

觀察以后發(fā)現(xiàn),誒,有個(gè)異或操作,woc,我不會(huì)還原異或!!!!!
不要慌,仔細(xì)想一想,對于t=tt=tt=t ^ (t&gt;&gt;i)(t&gt;&gt;i)(t>>i),我們在計(jì)算之前,可以考慮把ttt分成32i32 \over ii32?份(結(jié)果向上取整),為什么要這么做呢?因?yàn)榭梢钥醋鍪沁@樣的:

按照上面的想法,我們將現(xiàn)在的數(shù)分成三份(當(dāng)前的數(shù)按照二進(jìn)制表示,是一個(gè)010101串):X1X1X1,X2X2X2,X3X3X3
那么X1X1X1可以看作是t&lt;&lt;22t&lt;&lt;22t<<22,那么X2X2X2怎么算呢?我們可以這樣想:

這個(gè)想法很直觀,但是怎么在數(shù)學(xué)上實(shí)現(xiàn)呢?先讓t&gt;&gt;11t&gt;&gt;11t>>11,這樣就裁掉X3X3X3了,然后我們再讓ttt異或上X1&lt;&lt;11X1&lt;&lt;11X1<<11,因?yàn)橐粋€(gè)數(shù)異或自己等于零,異或零等于自己,所以說我們讓ttt當(dāng)中原來和X1X1X1相等的部分和X1&lt;&lt;11X1&lt;&lt;11X1<<11異或,這樣就在裁掉X1X1X1的同時(shí),保證了X2X2X2是完好的。X3X3X3按照一樣的思想,稍加推算也可以得出式子。
那么,現(xiàn)在我們有X1X1X1,X2X2X2,X3X3X3了,怎么進(jìn)一步還原ttt呢?注意到,現(xiàn)在的數(shù),實(shí)際上是原數(shù)異或上X1,X2X1,X2X1,X2兩段得到的,也就是說現(xiàn)在的X2X2X2是原數(shù)的X2X2X2和現(xiàn)在的X1X1X1異或得到的,所以說反過來異或一次,即X2X2X2異或X1X1X1,就是原數(shù)的X2X2X2那一段,X3X3X3同理,X1X1X1是沒有變的。所以會(huì)所我們再將這幾段拼接回去就好了。方法也很簡單,將X1&lt;&lt;22X1&lt;&lt;22X1<<22異或X2&lt;&lt;11X2&lt;&lt;11X2<<11再異或X3X3X3即可,可以自己手推一下,加深理解。
這樣的話,異或的逆運(yùn)算就解決了,而加又怎么辦呢?
其實(shí)這相當(dāng)解一個(gè)方程:
(2i+1)x≡t(mod232) \left(2^i+1\right)x\equiv t \pmod {2^{32}} (2i+1)xt(mod232)
顯然擴(kuò)展歐幾里得算法就可以搞定這一步,具體見代碼實(shí)現(xiàn)。

#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){//快速乘,直接乘會(huì)爆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; }

轉(zhuǎn)載于:https://www.cnblogs.com/Neonen/p/9832492.html

總結(jié)

以上是生活随笔為你收集整理的NOIP提高模拟-20181019-T1-加密的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。