题目大意
有一个字符串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
思路
本文是看教程:O(n)可以解决的2道题
习题的第一题,是比较好的思路。
虽然本次题目中没有用到数论的知识。
但是遇到数相关的题目,凡是提到了 K K 以及,就往欧拉公式,费马小定理上想。
欧拉函数ph(n): 所有小于n且与n互质的数的个数
比如说ph(12)=4,[1,5,7,11与12互质]欧拉定理: aph(n)=1(modn) a p h ( n ) = 1 ( m o d n )
n和a是正整数并且互质的时候,欧拉定理成立。
当欧拉公式中的n为质数的时候,显然 ph(p)=p−1 p h ( p ) = p − 1 ,则可得:费马小定理: a(p−1)=1(modp) a ( p − 1 ) = 1 ( m o d p )
这题目中
假设s是P进制的数。那么:
Smod(p−1)
S
m
o
d
(
p
−
1
)
=(S[0]∗Pn+S[1]∗Pn−1+...+S[n−1]∗P0)mod(p−1)
=
(
S
[
0
]
∗
P
n
+
S
[
1
]
∗
P
n
−
1
+
.
.
.
+
S
[
n
−
1
]
∗
P
0
)
m
o
d
(
p
−
1
)
=(S[0]+S[1]+...+S[n−1])mod(p−1)
=
(
S
[
0
]
+
S
[
1
]
+
.
.
.
+
S
[
n
−
1
]
)
m
o
d
(
p
−
1
)
因为 P%(P−1) P % ( P − 1 ) = 1。
所以判断各个位数上加起来能否被p-1整除就好了,若能整除答案就是p。
代码
#include<stdio.h>
#include<string>
#include<iostream>
#include<cstring>
using namespace std;
#define max_int(a,b) (a>b)? a:b
char S[100005];
int char2int(char a){
if('A'<=a && a<='Z') return a-'A'+10;
else return a-'0';
}
int main ()
{
scanf("%s",S);
int len = strlen(S);
int ans = 0;
int max_b = 0;
for(int i=0;i<len;i++){
ans += char2int(S[i]);
max_b = max_int(max_b,char2int(S[i]));
}
int flag = 0;
for(int i=max_b+1;i<=36;i++)
{
if(ans%(i-1)==0) {printf("%d\n",i);flag =1; break;}
}
if(flag == 0)
printf("No Solution\n");
}
Hit
费马小定理!