【C++】数的反序处理:数位/数的进制转换

7 篇文章 0 订阅

1.数的反序处理:数位

问题 B: 区间内的真素数

内存限制:128 MB时间限制:1.000 S

题目描述

找出正整数M和N之间(N不小于M)的所有真素数。

真素数的定义:如果一个正整数P为素数,且其反序也为素数,那么P就为真素数。

例如,11,13均为真素数,因为11的反序还是为11,13的反序为31也为素数。

输入

输入两个数M和N,空格间隔,1≤M≤N≤100000。

输出

按从小到大输出M和N之间(包括M和N)的真素数,逗号间隔。如果之间没有真素数,则输出No。

样例输入

10 35

样例输出

11,13,17,31

上一次写了素数筛模块,今天就会用到在这题;

当然本题最核心的还是如何获取数的逆序。在此不给出本题题解了,一本通都有.

拼装法

(这里面有一些方法是我自己为了方便命名的.)

新手村会用到的一些:

假设i是一个四位数,那么,(仅列举常见和方便的)

其千位:i/100/10;

其百位:i/100%10;

(/的优先级等同于%,*也一样,数学上易推知,与变量从左往右结合)

其十位:i%100/10

其个位:i%10==i%100%10

而一般又有这样的写法:

设两个整形变量:

h=i/100; w=i%100;

那么可简化为:

千位:h/10,百位h%10,十位w/10,个位w%10.

然后取反,各位乘1,10,100,1000即可。

但是这样有个坏处,如果给出的取值区间很大效率就会很低.所以,需要寻求更优解.

逐位移动法

这是一本通上介绍的一个好用的方法,并不使用数组。

int move(int n)
{
    int s = 0;
    while (n > 0)
    {
        s = s * 10 + (n % 10);
        n /= 10;
    }
    return s;
}

我们再来回顾一下,n%10是数的个位,所以第一次循环s=个位;第二次循环个位x10+新的n%10,而这个新的n就是原来的n除以10取整后的结果,原来的n/10即等于(千百十)。如此做可以把低位向高位迭代,高位不断跟在低位后面,完成逆序排序。

于是,改变while循环条件及内容可以改变取位数区间,这里不再赘述,仅举一例比如获取数n的后三位逆序:

int move(int n)
{
    int s = 0;
    while (3--)
    {
        s = s * 10 + (n % 10);
        n /= 10;
    }
    return s;
}

2.数的进制转换:

逐位移动法的变式

把这两个放在一起讲是因为他们的执行原理都很类似。

int turn(int x,int A)//A是目标进制数
{
    int m = 1, xA = 0;
    while (x != 0)//边界
    {
        if ((x % 10) < A)
        {
            xA += (x % 10) * m;
            m *= A;
            x /= 10;
        }
    }
    return xA;
}

首先A进制数位不能大于等于A;然后进入循环,从个位开始,十位,百位...分别乘以1,A,A^2即可。它是依靠x%10和x/=10两大支撑代码逐位遍历完成的。难点仍然是逐位移动的算法。

当然如果说清楚和理解透彻了之后,这样的算法也是随手构造即得.

递归算法

那么有没有不用逐位遍历的算法呢?有的。虽然也是遍历,但这次可以使用整个数去遍历。

这就是递归算法,它通过数n每次对k取模,自身除以k,取得目标数最低位,次低位...遍历出整个目标数.

char d[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
int turn(int x,int A)
{
    int r;
    r = x % A;
    x = x / A;
    if (x != 0)
        turn(x, A);
    cout<< d[r];//用ASCII码转会比较麻烦,9和A之间隔了几个符号.
    return 0;
}


int main()
{
    int x, m;
    cin >> x >> m;
    turn(x, m);
    cout << endl;
    
    return 0;
}

核心是递归思想,当然和上述移位的做法也有共同之处,实际应用可自行灵活处理.

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

城主_全栈开发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值