字符加密(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
12

cipher.out

32

cipher.in

3 1000000007
cab
z123z123d

cipher.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 字符串中的数据?

BZOJ 1031: [JSOI2007]字符加密Cipher

Java Cipher 解密中的奇怪字符

[JSOI2007]字符加密Cipher