不可表示的数(庞果网)完全解答
来源:互联网 发布:淘宝店铺图片上传视频 编辑:程序博客网 时间:2024/06/05 17:46
题目详情:
给定表达式[x/2] + y + x * y, 其中x,y都是正整数。其中的中括号表示下取整,例如[3/2] = 1 , [5/2] = 2。
有些正整数可以用上述表达式表达出来,例如正整数2,当取x = y = 1时,可以把2表达出来
( 解释下:当x=y=1时, [x / 2] + y + x * y = [1 / 2] + 1 + 1 * 1 = 0+1+1 = 2 );
有些数可以有多种方式表达,例如13可以由 x = 2 y = 4 以及x = 3 y = 3来表示;
有些数无法用这个表达式表达出来,比如3。
从1开始第n个不能用这个表达式表示出来的数,我们叫做an,例如a1=1 a2=3,给定n,求an。
输入:n值 1<=n<=40
输出:an % 1000000007的结果(因为结果较大,输出an %1000000007的结果)。
方法一:
算法思想:
⒈将要表示的数记为count,则count = [x/2] + y + x * y
⒉将式子变形count = (x + 1) * y + x / 2 ↔ y = (count - x/2 ) / (x + 1) ①
⒊所以当我们对count取不同值时,判断是否可以被表示,即判断①式中y 对于 x取(1、2、3…(x / 2 + x + 1 <= count)
能否得到整数值( (count - x/2 ) % (x + 1) == 0),若对于所有x, y均得不到整数,则count不可表示
⒋当x取1时,count = 2 * y, 所以不可表示的数一定是奇数
⒌所以我们将count从1开始以2为增补量不断测试,得到第n个不可表示的数就输出
代码如下:
#include <stdio.h>int givean(int n) { int i = 0, m;int count = 1, x; do { m = 1; for (x = 1; x / 2 + x + 1<= count; x++) {if ((count - x/2) % (x + 1) == 0){m = 0;break;} }//当count不可表示if (m == 1)i++;count += 2;}while (i < n);return (count - 2)% 1000000007;}int main(){ int n, x; scanf("%d", &n); x = givean(n); printf("%d\n", x); return 0;}
但是当我们运行时发现得到a1 = 1, a2 = 3, a3 = 15, a4 = 63, a5 = 4095, a6 = 65535, a7 = 262143很快。
当n = 8,算出(a8 = 1073741823) % 1000000007= 73741816却要两、三分钟。所以此方法理论是对的,却不合适。
相信很多人像我一样在,接下来是对上面算法进行各种优化,加大count的增补量、减小x的循环范围等等,但作用对于求解a40来说将微乎其微。
郁闷,疑惑之中在网上大查一番终于有所眉目,将借鉴整理如下。
方法二
下面仁兄博客将对此方法用到的数学方法,进行详细说明:
http://blog.csdn.net/oucyxc/article/details/9958035
相信看完以上博客我们知道:若一个数2^(m + 1)- 1是素数,则2^m - 1即为一个不可表示的数(m >= 1)
其实我们把2^p - 1为素数的数叫做梅森素数(百度可查)且对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,110503,132049,
216091,756839,859433,1257787,1398269,2976221,3021377,6972593,13466917,20996011,
24036583,25964951,30402457,32582657,37156667,42643801,43112609,57885161
目前只发现48个梅森素数。
编程的思想是我们可以把前四十个p值存在一个数组里,比如求第n个不可表示的数,则取第n个p值(假设为k),
计算第n个不可表示的数(2^(k - 1) - 1)% 1000000007 ↔ 2^(k - 1) % 1000000007 - 1,
但是我们会遇到一个问题2^(k - 1) 肯定会出现溢出.
这时我们可以,利用一个公式(A * B)mod C = ((A mod C) * (B mod C)) mod C
可推(a * b * c * d)mod e(若b, c, d是小于c的)= (((a mod e)* b) mod e * c) mod e * d) mod e
可推2^m mod c = ( (2^(m - 1) mod c) *2) mod c = ((2^(m - 2) mod c * 2) mod c * 2) mod c(即乘以一次二取一次摸,多少次方重复多少次)
所以我们边取摸边计算就不会溢出
代码如下:
#include <stdio.h>int givean(int n){int 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,110503,132049,216091,756839,859433,1257787,1398269,2976221,3021377,6972593,13466917,20996011};int num = p[n-1] - 1, s = 1, i;for (i = 1; i <= num; i++){s *= 2;s = s % 1000000007;}return s-1;}int main(){int n;scanf("%d", &n);printf("%d\n", givean(n)); return 0;}
- 不可表示的数(庞果网)完全解答
- 网题“不可表示的数”解答
- 网题“不可表示的数”解答
- 庞果网--不可表示的数
- 不可表示的数
- 不可表示的数——庞果网
- 亿阳信通:不可表示的数
- 不可表示数求解分析
- 不可表示的数[x/2] + y + x * y(英雄会)
- 不可表示的数[x/2] + y + x * y
- 庞果答题:亿阳信通:不可表示的数 的一个人见解(8-13第二次更新。)
- C语言,数的表示(整数)
- 浮点数的表示
- 浮点数的表示
- 定点数的表示
- 浮点数的表示
- 数的表示方法
- 浮点数的表示
- 今天天气好好
- C++Primer10.1
- java中碰到的常见异常收集
- oracle10g登录em后,提示“java.lang.Exception: Exception in sending Request :: null”
- Linux模块简介
- 不可表示的数(庞果网)完全解答
- oracle中dblink创建的两种方式
- HDU 1556 Color the ball
- Struts2中的校验器
- 智慧城市第二批试点落地 应规避激进风
- 5大常用的免费OCR软件
- Photoshop CS6简体中文完美破解版
- (Java 基础知识)Java TCP和UDP
- 数组遍历