名字听起来十分厉害啊...一道lzz的提交答案题。
提答题,我们看看题目,给出一个解密程序,叫你加密。
每个点有一个加密的sample和一些要加密的文本。
从题目中我们可以得到一些信息:
加密后一般为8/16个一组,字符集|S|=95。
那就来看数据吧。
Data 1
奥妙重重...overwatch是什么鬼啊
咦第一行15个字符,加密完120个字符。怕是8位ascii?
写完一测,样例挂了。
然后去完那个解密器,随手输了8位,invalid output?但是sample确实是1位=>8位啊。
后面想想,可能只是一个映射,不一定是ascii,反正有sample。我真是傻逼
测了测sample,发现里面95个字符都有,然后就没有了。
#include <iostream> #include <stdio.h> #include <math.h> #include <string.h> #include <time.h> #include <stdlib.h> #include <string> #include <vector> #include <fstream> #include <set> #include <map> #include <queue> #include <algorithm> #include <sstream> #include <stack> #include <iomanip> using namespace std; map<char,string> mpp; int main() { ifstream fin("toodifficult1_simple.in"); ifstream fin2("toodifficult1_simple.out"); string s,s2; while(getline(fin,s)) { getline(fin2,s2); int j=0; for(int i=0;i<s.length();i++) { string rp; for(int k=j;k<j+8;k++) rp.push_back(s2[k]); j+=8; mpp[s[i]]=rp; } } ifstream qwq("toodifficult1.in"); freopen("toodifficult1.out","w",stdout); while(getline(qwq,s)) { for(int i=0;i<s.length();i++) cout<<mpp[s[i]]; putchar(10); } }
Data 2
咦那个aaaaa...aaaa怎么看起来这么鬼畜啊...怕是有什么肮脏的****。
似乎是二进制减一?数一数,似乎是16位一分割。
咦那个一串一串的16个1是啥啊...懵逼
然后我们拉到第一行最后...咦最后有一大坨1,数一数好像是25*16个1...
excited!似乎和字母有关。
好像这里思路就中断了...玩玩那个解密程序好了。
input:400个1 output:""
input:15个0+401个1 output:"a"
嗯这很正常。
input:16个1+15个0+385个1 output:"b"
咦,shenmegui,难道这是分割字母的?
input:15个0+17个1+15个0+385个1 output:Invalid
哦好像是下标?
input:15个0+17个1+14个0+1+0+384个1 output:"ab"
input:14个0+1+0+16个1+15个0+385个1 output:"ba"
后缀数组!不同开头的后缀中间插16个1!
那么我们只要写一个暴力就行了233
#include <iostream> #include <stdio.h> #include <math.h> #include <string.h> #include <time.h> #include <algorithm> #include <stdlib.h> #include <string> using namespace std; char s[233333]; int rp[233333]; bool cmp(int a,int b) { for(int x=0;;++x) { if(s[a+x]!=s[b+x]) return s[a+x]<s[b+x]; } return 0; } int main() { freopen("toodifficult2.in","r",stdin); freopen("toodifficult2.out","w",stdout); string str; while(getline(cin,str)) { strcpy(s,str.c_str()); int n=str.size(); for(int i=0;i<n;i++) rp[i]=i; sort(rp,rp+n,cmp); int cur=‘a‘; for(int i=0;i<n;i++) { int r=rp[i]+1,p=s[rp[i]]; while(cur<p) printf("1111111111111111"), ++cur; int rs[16]; for(int k=0;k<16;k++) rs[k]=r%2, r/=2; for(int k=15;k>=0;k--) putchar(rs[k]+48); } while(cur<‘z‘) printf("1111111111111111"), ++cur; putchar(10); } }
Data 3
这输入是什么卵子啊...怎么这么乱啊...似乎是随机字符?
咦输出好像是64位啊...这是啥啊...是个整数?
咦输入可能也是整数?95进制?题目里还给了字符集?真刺激
S="a bcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,./\?;:‘"<>[]{}()|-_=+*&^%$#@!`~"
试试95进制然后转二进制?看了看好像不太像。
然后就gg了。(接下来去看了题解
woc要把这些大数分解质因数!pollard-rho!
然后把小的因数放在前面输出就行了。
#include <iostream> #include <stdio.h> #include <math.h> #include <string.h> #include <time.h> #include <stdlib.h> #include <string> #include <vector> #include <set> #include <map> #include <queue> #include <algorithm> #include <sstream> #include <stack> #include <iomanip> using namespace std; char gg[2333]; string S="a bcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,./\\?;:‘\"<>[]{}()|-_=+*&^%$#@!`~"; typedef long long ll; ll mul(ll a,ll b,ll n) { ll ans=0; while(b) { if(b&1) ans=ans+a, ans%=n; a=(a+a)%n; b>>=1; } return ans; } ll f(ll x,ll n) { return (mul(x,x,n)+1)%n; } ll gcd(ll a,ll b) {if(a<0) a=-a; if(b<0) b=-b; return b?gcd(b,a%b):a;} ll rho(ll n) { ll x=2, y=2, p=1; while(p==1) { x=f(x,n); y=f(f(y,n),n); p=gcd(x-y,n); } return p; } int main() { freopen("toodifficult3.in","r",stdin); freopen("toodifficult3.out","w",stdout); for(int i=0;i<S.size();i++) gg[S[i]]=i; string s; while(getline(cin,s)) { long long r=0; for(int i=0;i<s.size();i++) r=r*95+gg[s[i]]; ll a=rho(r),b=r/a; if(a>b) swap(a,b); int rs[32]; for(int k=0;k<32;k++) rs[k]=a%2, a/=2; for(int k=31;k>=0;k--) putchar(rs[k]+48); for(int k=0;k<32;k++) rs[k]=b%2, b/=2; for(int k=31;k>=0;k--) putchar(rs[k]+48); putchar(10); } }
Data 4
太毒了...待补
Data 5
喂出题人!MD5是什么鬼啊!不是吧
咦说好MD5呢怎么sample的out里面全是10010啥的...
然后去玩checker,发现可以输入字符串啊!然后checker确实会返回正确的字符串md5。
咦,这01串怕是有什么交易...咦第一个点输出好像长得差不多...我把所有东西压成一行当第一个点丢给checker解密好了。
真刺激,以下是解密后的全文(人工换行):
As you know, it‘s too difficult to solve this case.
So I will give you some problems, you just need to answer them.
All of the answers of these problems only consist of lower-case letters and numbers.
No.1 What do I like to play?
No.2 There is a poem including these words "gouliguojiashengsiyi", and then?
No.3 Who wrote this poem?
We often call the Mobius function mu(n).f(n)=sum (i=1 to n) mu(i).
No.4 Please work out the minimum of f(n) when n belongs to [1,10^9].
No.5 Please work out the maximum of f(n) when n belongs to [1,10^9].
No.6 The last problems may be the most difficult problem of this contest.
Can you work out C(6666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666,
2333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333) mod (1e100+7) ?
咦怎么只有6个问题...哦原来4和5两个问题分比较多。
No.1 overwatch(233
No.2 qiyinhuofubiquzhi(excited
No.3 jiangzemin(吃枣药丸
然后丢进checker一测,好像答案不对?md还要用第一题的那个加密程序啊
然后发现No.3 还是不对...后面想想好像是linzexu...(果然姿势水平不够高
接下来两个问题是什么卵子啊...梅滕斯函数的极值?我**怎么知道啊
暴力硬肛的话...除了空间都没什么问题。
额其实我们可以开三个bitset,每个10^9存质数和mu...
然后这样是过不了编译的...但是我们可以new...大概分配了4G内存,然后跑线筛,跑了200s,答案跑出来了...跑得电脑黑汗水流
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <algorithm> #include <iomanip> #include <time.h> #include <map> #include <bitset> using namespace std; #define MAXN 1000000000 int *ps,pn=0; bitset<10000000001> np; bitset<10000000001> *hm_; bitset<10000000001> *ms_; void shai() { long long qzh=1; bitset<10000000001>&hm=*hm_; bitset<10000000001>&ms=*ms_; np[1]=1; hm[1]=1; ms[1]=1; long long maxn=1, minn=1; for(int i=2;i<=MAXN;i++) { if(!np[i]) {ps[++pn]=i; hm[i]=1; ms[i]=0;} for(int j=1;j<=pn&&ps[j]*i<=MAXN;j++) { int p=ps[j]*i; np[p]=1; if(i%ps[j]) hm[p]=hm[i], ms[p]=!ms[i]; else {hm[p]=0; break;} } if(hm[i]) qzh+=(ms[i])?1:-1; maxn=max(maxn,qzh); minn=min(minn,qzh); if(i&131071);else cout<<i<<","<<minn<<","<<maxn<<" left"<<(1000000000*(clock()/(double)i)-clock())/1000.0<<"s\n"; } cout<<minn<<","<<maxn<<"\n"; } #define S2 80000000 int main() { cout<<"准备分配"<<(sizeof(np)*3+sizeof(int)*S2)/1024.0/1024.0/1024.0<<"GB内存!\n"; ps=new int[S2]; cout<<"进度33%\n"; hm_=new bitset<10000000001>(); cout<<"进度66%\n"; ms_=new bitset<10000000001>(); cout<<"进度100%\n"; shai(); }
接下来No.6的话...woc这...如果电脑上没有python的话还是算了吧QAQ
......答案果然是no。
最后输出用的东西
#include <iostream> #include <stdio.h> #include <math.h> #include <string.h> #include <time.h> #include <stdlib.h> #include <string> #include <vector> #include <fstream> #include <set> #include <map> #include <queue> #include <algorithm> #include <sstream> #include <stack> #include <iomanip> using namespace std; map<char,string> mpp; int main() { ifstream fin("toodifficult1_simple.in"); ifstream fin2("toodifficult1_simple.out"); string s,s2; while(getline(fin,s)) { getline(fin2,s2); int j=0; for(int i=0;i<s.length();i++) { string rp; for(int k=j;k<j+8;k++) rp.push_back(s2[k]); j+=8; mpp[s[i]]=rp; } } ifstream qwq("toodifficult5_u.out"); freopen("toodifficult5.out","w",stdout); while(getline(qwq,s)) { for(int i=0;i<s.length();i++) cout<<mpp[s[i]]; putchar(10); } }
Q:不行啊,考场机子一共就不到4G内存,那个点怎么做啊wtf
A:暴搜啊...不是给了checker吗...反正答案估计就不是很大...随便搜搜
(UPD:刚才测了测暴搜,跑得十分的慢啊,就不贴上来了...而且还时不时出个bug啥的...不过如果在程序中直接内嵌一个算md5的代码应该会快很多把)
然后这样就有80分啦23333这提答真是刺激啊