字符加密(cipher)
Posted kstt
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了字符加密(cipher)相关的知识,希望对你有一定的参考价值。
字符加密
Valentino 向往星空。。。某一天他脑洞大开地想要往太空中发送一串讯息,没准哪个外星文明接收到了呢?但是他突然想起一个问题,要是信息在传递过程中受到干扰,外星文明接收到错误的信息怎么办?如何校验信息的完整性?于是他找到了度娘:MD5 ( Message-Digest Algorithm ,信息-摘要算法 5)用于确保信息传输完整一致。它具有以下特点:
1、压缩性:任意长度的数据,算出的 MD5 值长度都是固定的。
2、容易计算:从原数据计算出 MD5 值很容易。
3、抗修改性:对原数据进行任何改动,哪怕只修改 1 个字节,所得到的 MD5 值都有很大区别。
4、弱抗碰撞:已知原数据和其 MD5 值,想找到一个具有相同 MD5 值的数据(即伪造数据)是非常困难的。
5、强抗碰撞:想找到两个不同的数据,使它们具有相同的 MD5 值,是非常困难的。
MD5 的作用是让大容量信息在用数字签名软件签署私人密钥前被“压缩”成一种保密的格式(就是把一个任意长度的字节串变换成一定长的十六进制数字串)。
例如: MD5(“g123g123d”) = ac75129df6ce688096da043ea0974c02。
除了 MD5 以外,比较有名的还有 SHA1 。
安全哈希算法( Secure Hash Algorithm )主要适用于数字签名标准 ( DigitalSignature Standard DSS )里面定义的数字签名算法( Digital Signature Algorithm DSA )。
对于长度小于 2 64 位的消息, SHA1 会产生一个 160 位的消息摘要。当接收到消息的时候,这个消息摘要可以用来验证数据的完整性。在传输的过程中,数据很可能会发生变化,那么这时候就会产生不同的消息摘要。 SHA1 有如下特性:不可以从消息摘要中复原信息;两个不同的消息不会产生同样的消息摘要。但是 Valentino 并不屑于使用这些办法(其实是看不懂),经 Valentino 研究,数字在传输过程中很难发生错误,所以他决定使用一种新的信息校验方法!(其实前面什么用都没有.......)Valentino 函数的定义:对于一个由数字和小写字母组成的字符串 S,两个整数 K,M,将 S 视为一个 P 进制数,定义:
Valentino(S, K, M) = K S MOD M
对于一个字串对应的进制 P,现作出如下规定:
S = “12445”,你应该将它视为一个 6 进制数:12445 6 = 1901 10 。
S = “c0ab5h”,你应该将它视为一个 18 进制数:c0ab5h 18 = 22736807 10 。
即,对于一个由数字和小写字母组成的字符串 S,将’a’视为 10,’b’视为 11,...,’z’视为 35,你应该找到最小的 P,使得 S 是一个合法的 P 进制数。现在,Valentino 手上有若干个由数字和小写字母组成的字符串。他选定了两个数 K,M,想求出每个字符串的 Valentino 函数的十进制表示。但是由于字符串实在太长了,Valentino 实在算不过来,所以他只好求助于你。
输入
第 1 行为两个正整数 K, M。
接下来每行一个由数字和小写字母组成的字符串,代表你要处理的字符串。
输出
每行一个整数,第 i 行输出第 i 个字符串的 Valentino 函数值,以十进制表示。
输入输出样例
cipher.in
2 1000000007
12cipher.out
32
cipher.in
3 1000000007
cab
z123z123dcipher.out
995596230
443537169
数据约定
1 ~ 3 字符串长度≤ 10
4 ~ 10 字符串长度≤ 10 5字符串个数≤ 20,2≤ K,M ≤2*10 9
tips:
字符串可能存在前导 0
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define FOR(i,a,b) for(register int i=a;i<=b;i++) 4 #define ROF(i,a,b) for(register int i=a;i>=b;i--) 5 using namespace std; 6 int k,m,n=0; 7 char a[21][100010]; 8 ll scan() 9 { 10 int as=0; 11 char c=getchar(); 12 while(c<‘0‘||c>‘9‘) c=getchar(); 13 while(c>=‘0‘&&c<=‘9‘) 14 { 15 as=(as<<3)+(as<<1)+c-‘0‘; 16 c=getchar(); 17 } 18 return as; 19 } 20 ll phi(int f) 21 { 22 ll as=f; 23 FOR(i,2,sqrt(f)) 24 { 25 if(f%i==0) 26 { 27 as=as/i*(i-1); 28 while(f%i==0) 29 f=f/i; 30 } 31 } 32 if(f>1) as=as*(f-1)/f; 33 return as; 34 } 35 ll ksm(int d,int z,int Mod) 36 { 37 if(z==0) return 1; 38 if(z==1) return d; 39 ll res=ksm(d,z>>1,Mod)%Mod; 40 res=(res*res)%Mod; 41 if(z&1) 42 res=(res*d)%Mod; 43 return res%Mod; 44 } 45 int main() 46 { 47 freopen("la.in","r",stdin); 48 freopen("la.out","w",stdout); 49 k=scan(); 50 m=scan(); 51 ll y=phi(m); 52 while(cin>>a[++n]); 53 n--; 54 FOR(i,1,n) 55 { 56 char c=‘0‘; 57 ll len=strlen(a[i]); 58 ROF(j,len-1,0) 59 { 60 if(a[i][j]>c) c=a[i][j]; 61 } 62 ll s=0; 63 if(c>=‘0‘&&c<=‘9‘) s=c-‘0‘+1; 64 else s=c-‘a‘+11; 65 // cout<<s<<endl; 66 ll sum=0; 67 FOR(j,0,len-1) 68 { 69 if(a[i][j]>=‘0‘&&a[i][j]<=‘9‘) 70 sum=(sum*s+a[i][j]-‘0‘)%y; 71 else 72 sum=(sum*s+a[i][j]-‘a‘+10)%y; 73 } 74 // cout<<sum<<" "<<y<<endl; 75 printf("%lld ",ksm(k,sum+y,m))
思路
欧拉函数的应用,我具体看欧拉函数
然后答案差不多就出来啦
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define FOR(i,a,b) for(register int i=a;i<=b;i++) 4 #define ROF(i,a,b) for(register int i=a;i>=b;i--) 5 using namespace std; 6 int k,m,n=0; 7 char a[21][100010]; 8 ll scan() 9 { 10 int as=0; 11 char c=getchar(); 12 while(c<‘0‘||c>‘9‘) c=getchar(); 13 while(c>=‘0‘&&c<=‘9‘) 14 { 15 as=(as<<3)+(as<<1)+c-‘0‘; 16 c=getchar(); 17 } 18 return as; 19 } 20 ll phi(int f) 21 { 22 ll as=f; 23 FOR(i,2,sqrt(f)) 24 { 25 if(f%i==0) 26 { 27 as=as/i*(i-1); 28 while(f%i==0) 29 f=f/i; 30 } 31 } 32 if(f>1) as=as*(f-1)/f; 33 return as; 34 } 35 ll ksm(int d,int z,int Mod) 36 { 37 if(z==0) return 1; 38 if(z==1) return d; 39 ll res=ksm(d,z>>1,Mod)%Mod; 40 res=(res*res)%Mod; 41 if(z&1) 42 res=(res*d)%Mod; 43 return res%Mod; 44 } 45 int main() 46 { 47 freopen("la.in","r",stdin); 48 freopen("la.out","w",stdout); 49 k=scan(); 50 m=scan(); 51 ll y=phi(m); 52 while(cin>>a[++n]); 53 n--; 54 FOR(i,1,n) 55 { 56 char c=‘0‘; 57 ll len=strlen(a[i]); 58 ROF(j,len-1,0) 59 { 60 if(a[i][j]>c) c=a[i][j]; 61 } 62 ll s=0; 63 if(c>=‘0‘&&c<=‘9‘) s=c-‘0‘+1; 64 else s=c-‘a‘+11; 65 // cout<<s<<endl; 66 ll sum=0; 67 FOR(j,0,len-1) 68 { 69 if(a[i][j]>=‘0‘&&a[i][j]<=‘9‘) 70 sum=(sum*s+a[i][j]-‘0‘)%y; 71 else 72 sum=(sum*s+a[i][j]-‘a‘+10)%y; 73 } 74 // cout<<sum<<" "<<y<<endl; 75 printf("%lld ",ksm(k,sum+y,m)); 76 } 77 }
ok啦,虽然我不知道为什么RE
以上是关于字符加密(cipher)的主要内容,如果未能解决你的问题,请参考以下文章
_bzoj1031 [JSOI2007]字符加密Cipher后缀数组
[BZOJ1031][JSOI2007]字符加密Cipher(后缀数组)
如何使用 OpenSSL::Cipher 加密 UTF-8 字符串中的数据?