【scau算法分析设计】11075强盗分赃|17963 完美数(c)

我说,别白嫖

目录

 11075 强盗分赃

题目:

输入格式

输出格式

输入样例

输出样例

提示

 代码:

17963 完美数

题目:

输入格式

输出格式

输入样例

输出样例

提示

 代码:

!tips:c语言次幂函数用 double pow(double a, double b) 可求


11075 强盗分赃

题目:

有天夜里5个强盗A、B、C、D、E抢到一大堆金币(金币个数不超过n个,n<=100000000),可是怎么也无法平均分成5份,
吵吵嚷嚷……

吵累了,只好先睡觉,准备第二天再分。

夜深了,一个强盗A偷偷爬起来,先拿了一个金币私下放自己口袋藏好,再将金币分为5等份,将自己的那一份再私藏好
就去睡觉了。

随着第二个强盗B也爬起来,也是私拿了一个金币再分5等份,也私藏起自己那份就睡觉去了。

后来的三个强盗C、D、E也都是这样办的。

问最初有多少个金币?(最初的金币个数有多种可能,请输出不超过n的所有可能,从小到大排列)

输入格式

输入一个数,n, n<=100000000。
请输出金币数不超过n的可能的初始金币个数。

输出格式

初始金币个数的多种可能(初始金币个数小于等于n)。

请输出不超过n的“所有的”可能,从小到大排列出,中间空格相连。

如果不超过n没有一种可能,输出impossible(无标点,无大写)
例如输入10,则输出impossible

输入样例

8000

输出样例

3121 6246

提示

此题所说的是:每个强盗私拿1个金币后都可以五等分,再私藏起1份,留下4份。
这样的初始金币个数是怎样的数,才能满足这个条件。

方法一:

此题若仅采用程序实现的话是较为简单的,可使用5次的递归算法或循环处理。
递归算法如下(循环处理也很简单):
int count = 0;
int func(int num)  //判断初始为num的数是否合适?合适返回1,不合适返回0
{  
    int temp = num-1;
    if(temp%5 == 0 && count<5)
    {  
        count++;
        return func(temp/5*4);
    }
    else
        if (count==5)
              return 1;
        else
              return 0;
}

但若要分析初始金币个数的通项函数表达就更难一些了。

方法二:
从最后一个强盗往前考虑,假设到第五个强盗E时,平均每个强盗得到x个金币
第五个强盗E藏掉一个金币后剩 5x 个 
第四个强盗D藏掉一个金币后剩 5(5x+1)/4 = 25x/4+5/4 = (x+1)/4 + ...
第三个强盗C藏掉一个金币后剩 5(25x/4+5/4+1)/4 = 125x/16+45/16 = 13(x+1)/16 + ...
第二个强盗B藏掉一个金币后剩 5(125x/16+45/16+1)/4 = 625x/64+305/64 = 49(x+1)/64 + ...
第一个强盗A藏掉一个金币后剩 5(625x/64+305/64+1)/4 = 3125x/256+1845/256 = 53(x+1)/256 + ...
因原来共有金币 3125x/256+1845/256+1 = 3125x/256+2101/256 = (12x+8)+53(x+1)/256 
这里是突破口:
x,(x+1)/4,13(x+1)/16,49(x+1)/64,53(x+1)/256 都应是整数,最后一个条
件 53(x+1)/256 是整数决定了初始金币的最小个数。所以 x=255 时最小的初始
金币总数(12x+8)+53(x+1)/256=3121个。

方法三:
或者这样分析,设金币总数n,由于5个强盗都是先藏一个后,发现余下的金币刚好均分5份,
所以设想在总数中加入4个新金币,则每个强盗占有的金币数不会改变(包括藏了的那一个),
从而每次分金币时这4个假想的金币会留存到后一层总数中,这使得每次分5份都是恰好的整数,
由此可见,n+4至少是5^5的整数倍,所以n的最小值为 5^5-4=3121。
其余可能的n值为 n = k*(5^5)-4,k为大于1的整数。

 代码:

数学分析法

#include <iostream>
#include <stdio.h>
#include <stdlib.h>

using namespace std;

int main()
{
    int n;
    scanf("%d",&n);
    if(n<3121) printf("impossible");
    int sum =0;
    for(int x=255;; x++){
        sum = (12*x + 8)+ 53*(x+1)/256;
        if(sum > n) break;
        if((53*(x+1)%256)==0)
            printf("%d ",sum);
    }
    return 0;
}

17963 完美数

题目:

现在请你以下列格式输出前8个完美数,每行一个完美数,前面是序号后面是完美数,中间用空格间隔。如:
1 6
2 xx
3 xxx
……

输入格式

输出格式

输出前8个完美数,每行一个完美数,前面是序号后面是完美数,中间用空格间隔。

输入样例

输出样例

1 6
2 xx
3 xxx
……
8 xxxxxxxx

提示

欧拉证明了,当2^p-1是素数时,2^(p-1)*(2^p-1)是完美数,而且偶完美数都具有这种
形式。目前还没有发现奇完美数。
一般认为存在有无穷多个完美数,但目前知道的2^p-1是素数的p只有47个,他们依次的
p值如下:
2 3 5 7 13 17 19 31 61 89 107 127 521 607 1279 2203 2281 3217 4253 4423 9689
9941 11213 19937 21701 23209 44497 86243 110503132049 216091 756839 859433 
1257787 1398269 2976221 3021377 6972593 13466917 20996011 24036583 25964951 
30402457 32582657 37156667 42643801 43112609 

这题要求输出前8个,用这个序列的前八个当做p,计算2^(p-1)*(2^p-1)即是完美数。

如果此题采用完美数定义(如果一个数的真约数之和等于这个自然数本身,则这个自然数
就称为完美数)来求解的话,产生不了前八个,会计算超时。

还有,此题需要采用64位的整数才可。

 代码:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
using namespace std;

int main()
{
    int perf[8] = {2,3,5,7,13,17,19,31};
    for(int i=0 ;i<8; i++)
    {
        long long int sum = pow(2,perf[i]-1)*(pow(2,perf[i])-1);
        printf("%d %lld\n",i+1,sum);
    }
}

按照提示写即可。用数组存储预先数。

!tips:c语言次幂函数用 double pow(double a, double b) 可求

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
11075 强盗分赃 时间限制:1000MS 内存限制:65535K 提交次数:0 通过次数:0 题型: 编程题 语言: 无限制 Description 有天夜里5个强盗A、B、C、D、E抢到一大堆金币(金币个数不超过n个,n<=100000000),可是怎么也无法平均分成5份,吵吵嚷嚷…… 吵累了,只好先睡觉,准备第二天再分。 夜深了,一个强盗A偷偷爬起来,先拿了一个金币私下放自己口袋藏好,再将金币分为5等份,将自己的那一份再私藏好就去睡觉了。 随着第二个强盗B也爬起来,也是私拿了一个金币再分5等份,也私藏起自己那份就睡觉去了。 后来的三个强盗C、D、E也都是这样办的。 问最初有多少个金币?(最初的金币个数有多种可能,请输出n以内所有可能,从小到大排列) Input 输入一个数,n。 请输出金币数不超过n的可能的初始金币个数。Output 初始金币个数的多种可能(初始金币个数小于等于n)。 请输出不超过n的“所有的”可能,从小到大排列出,中间空格相连。 如果不超过n没有一种可能,输出impossible(无标点,无大写) 例如输入10,则输出impossible Sample Input 8000 Sample Output 3121 6246 Hint 此题所说的是:每个强盗私拿1个金币后都可以五等分,再私藏起1份,留下4份。 这样的初始金币个数是怎样的数,才能满足这个条件。 方法一: 此题若仅采用程序实现的话是较为简单的,可使用递归算法,或循环处理。递归算法如下(循环处理也很简单): int count = 0; int func(int num) //判断初始为num的数是否合适 { int temp = num-1; if(temp%5 == 0 && count<5) { count++; return func(temp/5*4); } else if (count==5) return 1; else return 0; } 但若要分析初始金币个数的通项函数表达就更难一些: 方法二: 从最后一个强盗往前考虑,假设到第五个强盗E时,平均每个强盗得到x个金币 第五个强盗E藏掉一个金币后剩5x个 第四个强盗D藏掉一个金币后剩5(5x+1)/4=25x/4+5/4 第三个强盗C藏掉一个金币后剩5(25x/4+5/4+1)/4=125x/16+45/16 第二个强盗B藏掉一个金币后剩5(125x/16+45/16+1)/4=625x/64+305/64 第一个强盗A藏掉一个金币后剩5(625x/64+305/64+1)/4=3125x/256+1845/256 原来共有金币3125x/256+1845/256+1=3125x/256+2101/256=(12x+8)+53(x+1)/256 这里是突破口:53(x+1)/256 是整数,因金币数是整数,所以x=255时最小的初始金币总数3121个。 方法三:或者这样分析,设金币总数n,由于5个强盗都是先藏一个后,发现余下的金币刚好均分5份, 所以设想在总数中加入4个新金币,则每个强盗占有的金币数不会改变(包括藏了的那一个), 从而每次分金币时这4个假想的金币会留存到后一层总数中,这使得每次分5份都是恰好的整数, 由此可见,n+4至少是5^5的整数倍,所以n的最小值为5^5-4=3121。 其余可能的n值为n=k*(5^5)+4,k为大于1的整数。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值