编程题1:
求一个n(1<n<=36)进制正整数除以m(1<m<=36)的余数。
输入两行,第一行为n,m;第二行包含一个整数,由连续进制字符组成,若发现非法字符(比如空格;在10进制下,‘a’-'z’也属于非法字符),表示整数结束。
#include <iostream>
#include<vector>
#include<string>
using namespace std;
class Solution {
public:
//若先对字符串求和再求余,可能导致内存溢出。根据数学知识:(x1+x2+x3)%m=x1%m+x2%m+x3%m,故可对每一位上的元素利用快速幂思想分别求幂,然后相加
//本题注意点及陷阱:若发现非法字符(比如空格;在10进制下,'a'-'z'也属于非法字符),表示整数结束
int res = 0;
int check(int n,string ss,int m) {
if (ss.size() == 0) return 0;
//1、先找到合法字符 O(n)
int size=0;
if (ss.find(' ') != string::npos)
size = ss.find(' ');
else {
for (int i = 0; i < ss.size(); i++) {
if (ss[i] >= '0' && ss[i] <= '9' && ss[i] - '0'>=n) {
size = i;
break;
}
else if (ss[i] >= 'a'&&ss[i] <= 'z' && ss[i] - 'a' + 10 >= n) {
size = i;
break;
}
else
size = ss.size();
}
}
//2、利用快速幂求解每一位元素的幂 O(nlogn)
for (int i = 0; i < size; i++) {
int j = size - i - 1;
int ans = 1;
while (j)
{
if (j & 1) ans *= n % m;
n *= n % m;
j >>= 1;
}
int tmp = 0;
if (ss[i] >= '0'&&ss[i] <= '9')
tmp = ss[i] - '0';
else if (ss[i] >= 'a'&&ss[i] <= 'z')
tmp = ss[i] - 'a' + 10;
ans = ans * tmp % m;
res += ans;
}
return res%m;
}
};
int main()
{
int n, m;
printf("input n m: ");
cin >> n >> m;
string str;
printf("input str: ");
//注意:当同时使用cin>>,getline()时,在cin>>输入流完成之后,getline()之前,
//需要通过 str = "\n";getline(cin, str);的方式将回车符作为输入流cin以清除缓存,
//如果不这样做的话,在控制台上就不会出现getline()的输入提示,而直接跳过,因为程序默认地将之前的变量作为输入流。
str = "\n"; getline(cin, str);
getline(cin, str);
Solution s;
cout << s.check(n,str,m) << endl;
return 0;
}
若大家有更好的解法或者我的解法有问题,欢迎大家指教!