字符加密 cipher

  评测传送门

Description:

  Valentino 函数的定义:
  对于一个由数字和小写字母组成的字符串 S,两个整数 K,M,将 S 视为一个 P 进制数,定义:
  Valentino(S, K, M) = KS mod M
  对于一个字串对应的进制 P,现作出如下规定:
  S = “12445”,你应该将它视为一个 6 进制数:124456 = 190110 。
  S = “c0ab5h”,你应该将它视为一个 18 进制数:c0ab5h18 = 2273680710 。
  即,对于一个由数字和小写字母组成的字符串 S,将’a’视为 10,’b’视为 11,...,’z’视为 35,你应该找到最小的 P,使得 S 是一个合法的 P 进制数。
  现在,Valentino 手上有若干个由数字和小写字母组成的字符串。他选定了两个数 K,M,想求出每个字符串的 Valentino 函数的十进制表示。但是由于字符串实在太长了,Valentino 实在算不过来,所以他只好求助于你。

Input
  第 1 行为两个正整数 K, M。
  接下来每行一个由数字和小写字母组成的字符串,代表你要处理的字符串。

Output
  每行一个整数,第 i 行输出第 i 个字符串的 Valentino 函数值,以十进制表示。

正解:

我觉得solution讲得超级清楚啊(图点开看还是挺清楚的)

但是要补充解释一个地方:x的含义是 kpi,pi是p的i次方

CODE:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<string>
 4 #include<cstring>
 5 #define R register
 6 #define go(i,a,b) for(R int i=a;i<=b;i++)
 7 #define yes(i,a,b) for(R int i=a;i>=b;i--)
 8 #define M 100000+1
 9 #define ll long long
10 using namespace std;
11 ll k,m,n,x,len,a[M],as;
12 string s;
13 ll ksm(ll x,ll y)
14 {
15     ll ans=1;
16     while(y)
17     {
18         if(y&1) ans=ans*x%m;
19         x=x*x%m;y>>=1;
20     }
21     return ans%m;
22 }    
23 int main()
24 {
25     scanf("%lld%lld",&k,&m);
26     while(cin>>s)
27     {
28         len=s.length()-1;n=0;as=1;x=k;
29         go(i,0,len)
30         {
31             if(s[i]>='0'&&s[i]<='9') a[i]=s[i]-'0';
32             else a[i]=s[i]-'a'+10;
33             n=max(n,a[i]);
34         }n+=1;
35         yes(i,len,0)
36         {
37             as=as*ksm(x,a[i])%m;
38             x=ksm(x,n);
39         }
40         printf("%lld\n",as);
41     }
42     return 0;
43 }
View Code

猜你喜欢

转载自www.cnblogs.com/forward777/p/10359981.html