<题单>#4题解
题目链接:http://www.xujcoj.com/Home/Contest/cs/cid/766/ctype/1
1.可以整除的数字
题意:
给你一个正整数n,判断n能否被3、5、8、11中的一个或多个数整除。(n<1e50)
题解:
由于正整数过大,因此n用字符串进行存储,只要判断(n%3,5,8,11)是否等于0,也就是课上讲的大数取模,利用大数取模来进行判断即可。
大数取模:
一个数字abc%k
可以拆解为(((a*10)+b)*10+c)%k,根据乘法取模的性质,将取模运算符分配即可得到结果。
上板子
ll BigIntMod(string a, ll mod)
{
ll sum = 0, n = a.length();
for (int i = 0; i < n; i++)
{
sum = sum * 10 + a[i] - '0';
sum %= mod;
}
return sum;
}
2.二进制取模
题意:
给你一个二进制数字,输出它在十进制下对1000000007取模的结果。
题解:
用字符串存这个数字,对于数字1010,可以分解为 ((((1*2)+0)*2+1)*2+0),同上题的大数取模思想,读者请触类旁通。
3.噬元兽的难题
题意:
输入三个18进制的数a,b,c,求其乘积
题解
将其转化成10进制进行乘法运算,再将其转换为18进制输出即可。
进制转换模板
// 把m进制的a转为10进制
ll convert_10(ll m, string a)
{
ll sum = 0, n = a.length();
for (int i = 0; i < n; i++)
{
if (a[i] >= '0' && a[i] <= '9')
sum = sum * m + a[i] - '0';
else
sum = sum * m + a[i] - 'A' + 10;
}
return sum;
}
// 把十进制的num转成m进制
void convert_m(ll num, ll m)
{
int a[100], x = 0;//a数组大小自行调整
while (num)
{
a[x++] = num % m;
num /= m;
}
for (int i = x - 1; i >= 0; i--)
{
if (a[i] >= 0 && a[i] <= 9)
cout << a[i];
else
cout << char(a[i] - 10 + 'A');
}
cout << endl;
}
4.进制转换
板子题目
5.进制转换-2
题意:
给你一个二进制或十六进制的数字,请你完成他们之间的转换。
题解:
转化的规则:16进制转化成2进制每一位对应转化成2进制的4位,2进制转为16进制每四位转化成16进制的一位(不明白的话可以百度加深理解)。
上述规则理解了之后就可以进行代码的处理了,首先判断是2进制还是16进制,简单循环判断即可。
二进制:
首先判断2进制的位数,如果不是4的倍速就在前面添加前导0
while (s.length() % 4 != 0)s = '0' + s;
对每4位进行2进制转10进制的处理,得到数字t。如果数字t<=9,直接输出,否则的话输出char(t-10+'A')。
十六进制:
16进制转化成10进制,然后10进制转化成2进制。16进制转10进制:如果对应char<='9',对应的十进制t=char-'0',反之,t=ch-'A'+10
10进制转2进制直接套板子,转化成的二进制一定要4位,打个比方,比如11,要对其补前导0,变为0011。最后将我们的二进制依次存储到我们的ans字符串之中,最后要清除ans的前导0即可。
6.进制转换-3
题意:
输出数字在计算机中的存储形式,每8位用一个空格隔开,最后换行
题解:
位运算题,我们将二进制里每一位数存储到数组里,然后倒序输出即可。
for (int i = 1; i <= 32; i++)
{
r[i] = (x & 1);
x >>= 1;
}
** 对(x&1)的解释**:一个数字的末尾如果是1,那么其数字&1为1,反之数字&1为0,我们不断对其进行&1运算,然后在右移执行32次,每次存到数组r里面,最后倒序输出即可。
7.数列乘积
题意:
题解:
这题的话,用大数字取模运算+慢速乘,唯一要注意的地方是,大数取模之中,(ans*10)这一块也要慢速乘,因为ans的取值范围和mod一样,而mod<=1e18,因此进行*10的操作会炸long long。
慢速乘板子:
ll mul(ll a, ll b,ll mod)
{
ll ans = 0;
while (b)
{
if (b & 1)
{
ans = ans + a;
ans %= mod;
}
a = (a << 1) % mod;
b >>= 1;
}
return ans;
}
8.高次幂运算-3
题意:
计算 a 的 b 次方对 1e9+7 取模以后的结果,(1 <= a,b <= 1e100)
题解:
大数字取模+快速幂运算
根据费马小定理
mod为素数时,\(a^b\%mod=a^{(b\%(mod-1))}\%mod\)
对于a我们也进行大数取模的化简,最后将结果用快速幂求得即可。
9.消失的零
题意:
一个数列,正整数,没有存在0的数字,现在求这个数列的第x项是多少。
题解:
实际上这题是9进制存储的变式,通常来说我们转化成其9进制即可。
唯一特别的地方就是,每一位的进制存储范围是从传统9进制的[0,8],变式为[1,9]的 。我们仔细观察,在我们对10进制的数字循环迭代的时候,0是如何出现的?,当我们数字x%9=0的时候,传统9进制对应的位数就是0,但是本题每一位范围的是[1,9],因当x%9=0的时候,我们将其化成(x-1)%9+1,就能改变其的取值范围了
while (x)
{
int t = x % 9;
if (t == 0)//被整除的时候 留一位
{
s.push((x - 1) % 9 + 1);
x = (x - 1) / 9;
}
else//正常操作
{
s.push(x % 9);
x = x / 9;
}
}