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 }