51nod 1166 K进制下的大数 (快速幂)

有一个字符串S,记录了一个大数,但不知这个大数是多少进制的,只知道这个数在K进制下是K - 1的倍数。现在由你来求出这个最小的进制K。
例如:给出的数是A1A,有A则最少也是11进制,然后发现A1A在22进制下等于4872,4872 mod 21 = 0,并且22是最小的,因此输出k = 22(大数的表示中A对应10,Z对应35)。
 
Input
输入大数对应的字符串S。S的长度小于10^5。
Output
输出对应的进制K,如果在2 - 36范围内没有找到对应的解,则输出No Solution。
Input示例
A1A
Output示例
22


其实可以当成快速幂来算,由于ab%mod ==  ((a%mod)(b%mod))%mod,(a+b)%mod == (a%mod + b%mod)%mod,比如A1A用22进制进制表示时为10*22^2+1*22+10*22^0 ,设当前为k进制,其实整个数模k-1为∑s[i]*pow(k,len-i-1) %(k-1)。这样就转换成快速幂了。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 1e5+10;
 4 char s[N];
 5 int len;
 6 map<char,int> mp;
 7 int pow_mod(int x, int n, int mod) {
 8     int y = 1;
 9     while(n) {
10         if(n&1) y = y*x%mod;
11         x = x*x%mod;
12         n >>= 1;
13     }
14     return y;
15 }
16 bool ok(int k) {
17     int ans = 0;
18     for(int i = 0; i < len; i ++) {
19         ans += pow_mod(k,(len-i-1)%(k-1),k-1)*mp[s[i]]%(k-1);
20     }
21     ans %= (k-1);
22     return ans == 0;
23 }
24 int main() {
25     cin >> s;
26     len = strlen(s);
27     for(int i = 0; i < 10; i ++) mp['0'+i] = i;
28     for(int i = 0; i < 26; i ++) mp['A'+i] = i+10;
29     int k = 2;
30     for(int i = 0; i < len; i ++) k = max(k, mp[s[i]]);
31     for( ++ k; k <= 36; k ++) {
32         if(ok(k)) return 0*printf("%d\n",k);
33     }
34     printf("No Solution\n");
35     return 0;
36 }

 

posted @ 2018-09-01 19:59  starry_sky  阅读(286)  评论(0编辑  收藏  举报