PTA 翁恺 7-42 整除光棍

这里所谓的“光棍”,并不是指单身汪啦~ 说的是全部由1组成的数字,比如1、11、111、1111等。传说任何一个光棍都能被一个不以5结尾的奇数整除。比如,111111就可以被13整除。 现在,你的程序要读入一个整数x,这个整数一定是奇数并且不以5结尾。然后,经过计算,输出两个数字:第一个数字s,表示x乘以s是一个光棍,第二个数字n是这个光棍的位数。这样的解当然不是唯一的,题目要求你输出最小的解。

提示:一个显然的办法是逐渐增加光棍的位数,直到可以整除x为止。但难点在于,s可能是个非常大的数 —— 比如,程序输入31,那么就输出3584229390681和15,因为31乘以3584229390681的结果是111111111111111,一共15个1。

输入格式:

输入在一行中给出一个不以5结尾的正奇数x<1000)。

输出格式:

在一行中输出相应的最小的sn,其间以1个空格分隔。

输入样例:

31
 
结尾无空行

输出样例:

3584229390681 15
整体思路:
显然这里按照传统的大数除法是行不通的,存储空间不够,数据过大也会产生精度丢失,只能另辟捷径了。
在传统的除法之中,比如144 / 6 ,先判断 1 < 6 ,无法用1除,改用14(14=1*10+4)除,14 / 6 = 2(整数除法),余数为2(不为0,继续进行操作),
继续用2*10+4=24,24除以6,商为4,余数为0结束操作。
可以巧妙地采用模拟除法,被除数s(s不是固定为某个值,初始值为第一位数,本题为1),除数x,余数为y。第一步先判断s是否大于等于x,满足则开始相除,
不满足则s = s * 10 +1直至s >= x(这里的1为第二位数,仅仅是本题为1)然后取余,y = s / x;利用整数除法得出第一位数s / x;类比传统除法,此时的
s = s * 10 + 1;然后判断y是否为0,为0则结束操作,否则继续循环。
整体代码:
#include <stdio.h>

int main (void){
    int x = 0,y = 1;
    int s = 1;
    int count = 1;
    scanf ("%d",&x);
    while(s < x)
    {
        s = s * 10 + 1;
        count++;
    }
    while (y != 0)
    {
        y = s % x;
        printf("%d",s / x);
        s = y * 10 + 1;
        count++;
    }
    printf(" %d",count - 1);
    return 0;
}

讨论:

  • y=0后到结束循环之前,count多加了一次,所以最后输出时要减一,也可以在输出s/x后面加上判断语句跳出循环
  • 模拟除法非常巧妙,与数组结合可以运算非常大的数。
 
 
posted @ 2021-10-20 20:17  海萌萌萌萌萌萌  阅读(143)  评论(0编辑  收藏  举报