PTA 7-178 吸血鬼素数

PTA 7-178 吸血鬼素数

分数 10
作者 林生佑
单位 浙江传媒学院

1994年,美国数学家皮科夫在一篇文章中首次提出了吸血鬼数。如果一个2n(n是自然数)位的自然数等于自己各个数字任意组成的两个n位数的乘积,那么这个自然数就叫吸血鬼数。其中这两个n位数都被称为獠牙或尖牙。比如1260=21×60,所以1260是一个吸血鬼数。注意两个尖牙的个位数不能同时为0,例如虽然126000=210×600,但126000却不是吸血鬼数。在此基础上,2002年,数学家里维拉定义了吸血鬼素数。如果吸血鬼数的两个尖牙都是素数,则这两个尖牙都叫吸血鬼素数。例如,117067=167×701,而167和701都是素数,所以167和701都是3位吸血鬼素数。

输入一个正整数n(小于1000),请判断它是否吸血鬼素数。如果是,打印YES,否则打印NO。

输入格式:
一个小于1000的正整数n

输出格式:
YES或者NO

输入样例:

701

输出样例:

YES

代码长度限制
16 KB
C (gcc)
时间限制
400 ms
内存限制
64 MB
其他编译器
时间限制
400 ms
内存限制
64 MB

#include <stdio.h>
#include <math.h>
int prime(int flag, int x){    //判断是否为素数
    if(x == 1)
        flag = 1;    //返回不是素数
    else if(x == 2)
        flag = 0;    //返回是素数
    else{
        for(int i = 2; i < x; i++){
            if(x % i == 0){
                flag = 1;
                break;
            }else
                flag = 0;
        }
    }
    return flag;
}
int digit(int x){    //求n的位数
    int count;    //记录位数
    for(count = 1; ; count++){
        x /= 10;
        if(x == 0)
            return count;
    }
}
int main(){
    int n, m;    //两个尖牙数
    int nm[10], vamp[10];    //用数组统计各数字出现的次数
    int counts = 0;    //标记各数字出现的次数,默认相等
    int flag = 0, decimals;    //标记素数flag,默认是素数; n的位数decimals
    int origin;    //吸血鬼数的位数
    int vampNumb;    //吸血鬼数
    scanf("%d", &n);    //输入第一个尖牙数
    int x;    //函数参数
    if(n > 0  && n < 1000){
        x = n;
        flag = prime(flag, x);    //判断第一个尖牙n是否是素数
        if(flag == 1){    //若不是素数,则一定不是吸血鬼素数
            printf("NO");
            return 0;
        }else if(flag == 0){    //是素数
            decimals = digit(x);    //求n的位数
            origin = 2 * decimals;    //吸血鬼数的位数
        }
        for(int j = pow(10, origin - 1); j < pow(10, origin); j++){    //寻找第二个尖牙数
            if(j % n == 0){
                m = j / n;
                x = m;
                vampNumb = j;
                flag = prime(flag, x);
                if(flag == 0 && digit(x) == decimals && n % 10 != 0 && m % 10 != 0){
                    //如果第二个尖牙数是素数;第二个尖牙数的位数等于第一个尖牙数的位数;两个尖牙数的个位不能同时为0
                    for(int i = 0; i <= 9; i++){    //遍历数组
                        nm[i] = 0;    //初始化
                        vamp[i] = 0;
                    }
                    int a = m, b = n, c = vampNumb;
                    while(a > 0){    //处理m,统计其中各个数字的出现次数
                        nm[a % 10]++;
                        a /= 10;
                    }
                    while(b > 0){    //处理n,统计其中各个数字的出现次数
                        nm[b % 10]++;
                        b /= 10;
                    }
                    while(c > 0){    //处理vampNumb,统计其中各个数字的出现次数
                        vamp[c % 10]++;
                        c /= 10;
                    }
                    counts = 0;
                    for(int k = 0; k <= 9; k++){
                        if(nm[k] != vamp[k]){    //若数字次数有一次数出现不相等
                            counts = 1;
                            break;
                        }
                    }
                    if(counts == 0){
                        printf("YES");
                        return 0;
                    }
                }
            }
        }
        if(flag == 1){
            printf("NO");
        }
    }
    return 0;
}

解题思路:
设:vampNumb = n * m ,vampNumb 是吸血鬼数,n 是输入的第一个尖牙数
step1:先判断 n 是不是素数,如果不是素数就不可能是吸血鬼素数,直接输出"NO",结束程序。
step2:如果是素数,则算出 n 的位数 decimals;
step3:根据 decimals 得出吸血鬼数 vampNumb 的位数为 2 * decimals
step4:寻找另一个尖牙数 m,当且仅当 vampNumb % n == 0。求出的 m 也应该是吸血鬼素数,所以还要判断 m 的位数是否也是 decimals 位数,m 是否也是素数。
step5:因为吸血鬼数 vampNumb 等于自己各个数字任意组成的两个 n 位数的乘积,所以 vampNumb 各个数字出现的次数等于 n 和 m 各个数字出现的次数之和。
step6:可以建立两个数组(变量名称是个人习惯) int nm[10],vamp[10];全部元素初始化为0,分别用来记录 vampNumb 各个数字出现的次数和 n 和 m 各个数字出现的次数之和,如果完全相同,就说明 n 和 m 是吸血鬼素数。
step7:如果 vampNumb 一直到范围上限都没找到对应的 m,则 n 不是吸血鬼素数。

归属知识点:
函数
数组
选择结构
循环结构

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值