不可表示的数[x/2] + y + x * y
前端是时间在庞果网上看到不可表示的数的编程题(如下),我自己也试着解答了一下,写的算法虽然没有没有错,但是跑了一些还只是跑到a8,后来到自己整理一下网上的解答过程,虽然解答写的很清晰,但是有些知识还是不是很清楚,要弄清楚还是得自己在找其他的资料。
给定表达式[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的结果)。
推理解答过程:
1、 对[x/2] + y + x * y分析,试探:x=1,原式=2y,表示所有偶数,即对所有偶数都能用此式表示,故后文重点讨论哪些奇数不能被其表示(本文讨论的所有奇偶数都为非负数)。
2、 对x分为4n,4n+1,4n+2,4n+3四种情况讨论。
容易得到,x=4n+1时,不论y取何值,原式必为偶数,与1)中情况重复,故舍去不讨论;
x=4n时,y=2m+1才能保证原式为奇数,其中要保证n>0;
x=4n+2时,y=2m才能保证原式为奇数,其中要保证m>0;
x=4n+3时,y=2m或2m+1都能使原式为奇数;
故只讨论后三种情况。
3、 把x=4n,y=2m+1代入原式易得2(m+n)+8mn+4n+1、n>0;
把x=4n+2,y=2m代入原式易得2(m+n)+8mn+4m+1、m>0;
明显,这两种情况可表示的奇数是相同的,故只需研究其中一种即可。
总结一下,目前已知原式对所有偶数可表示,对哪些奇数可表示呢?我们要研究的情况只有两种x=4n+2(即x=4n)与x=4n+3时的情况。
4、 对x=4n+2时,不限制y的奇偶性,此情况下,原式可表示为2n+3y+4ny+1;
对x=4n+3时,不限制y的奇偶性,,此情况下,原式可表示为2n+4y+4ny+1;
下面我们重点讨论这两种情况表示的奇数包括哪些。
5、 对x=4n+3,原式=2n+4y+4ny+1=2(n+1)(2y+1)-1,即表示一个奇数(2y+1)的偶数倍减1。也就是说x=4n+3情况时,表示的奇数都具备一个特征:这个奇数可以写成一个奇数的偶数倍减1。
故我们可以得到下面的结论:在x=4n+3的情况下,如果偶数B能写成一个奇数的偶数倍,即奇数与偶数的乘积,那么奇数A=B-1可以被原式表示。
其逆否命题:在x=4n+3的情况下,奇数A=B-1不可以被原式表示,则偶数B不能写成奇数与偶数的乘积,即其因子分解只能写成偶数与偶数的乘积。
一个偶数因子分解只能写成偶数与偶数,只有2的幂了。
故得到结论:在x=4n+3的情况下,不可以被原式表示的奇数都是2的幂减1。
6、 对x=4n+2,原式=2n+3y+4ny+1=[(4n+3)(2y+1)-1]/2,即表示两个奇数的积减1的差的一半。也就是说x=4n+2情况时,表示的奇数都具备一个特征:这个奇数可以写成两个奇数的积(4n+3)(2y+1)减1的差的一半。
换句话说,在x=4n+2的情况下,原式所能表示的奇数A都可以写成两个奇数的积减1的差的一半。反过来,2A+1必定能写成两个奇数的积。
而对任意的2A+1必为奇数,它要么能写成两个奇数的积,要么是素数。
故得到结论:在x=4n+2的情况下,不可以被原式表示的奇数A都是某个素数减1的差的一半。
7、 把1)、5)与6)的结论综合起来,对任意正整数x、y,如果不能被原式表示,它必定是奇数,这个奇数必定是2的幂减1,同时是某个素数减1的差的一半。
用形式化语言表达,对任意正整数x、y,不能被[x/2] + y + x * y表示的数,必定可以写成2^p-1,且2^(p+1)-1是一个素数。
8、 于是我们得到这个问题的解答:an中的元素都满足2^p-1且2^(p+1)-1是素数。
--------------------------------------------------------------------------------------
编程求解:
问题从数学上已经解决了,并得到了一个漂亮的解答。但如何求2^p-1,还要判断2^(p+1)-1是否为素数,这都是非常困难。
一步步来,求素数,传统方法当然是素性检测,以前写过一个拉宾米勒测试,很复杂。但突然意识到对2^p-1如果是素数的话,数论被叫做梅森素数,前人肯定有总结。
百度一下,前40个梅森素数的幂指数(p+1)取值为: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。
有了梅森素数,只要求相应的2^p-1即可。素数的问题是解决了,但2^20996011是个什么概念,天文数字,再强大计算机一时半会儿也算不出来。幸好题目是拿an对1000000007取模。通过模运算可以简化问题。
模运算(2^p-1)%N=(2^p%N-1)%N,在这里等于2^p%N-1。但下面一个问题来了2^p%N怎么求?
2^p%N是一个庞大的数,传统的方法是递归,无论从空间还是时间上来说都不解决问题。幸好往日有积累,对这种变态需求,当然有特殊手段。运用蒙哥马利算法可以迅速解决,秒杀之。
最后得到an的前40个数:1,3,15,63,4095,65535,262143,73741816,536396503,140130950,487761805,319908070,106681874,373391776,317758023,191994803,416292236,110940209,599412198,383601260,910358878,532737550,348927936,923450985,470083777,642578561,428308066,485739298,419990027,287292016,202484167,389339971,848994100,273206869,853092282,411696552,876153853,90046024,828945523,697988359。
提交代码的时候,写成枚举,成功!
求解程序:
#include <iostream>
using namespace std;
//蒙哥马利算法
unsigned __int64 mod_exp(int a,int b0,unsigned long n)
{
if(a > n ) a %= n;
int i;
unsigned __int64 d = 1;
int b[35];
for(i=0; i < 35; ++i )
{
b[i]= b0%2;
b0/= 2;
if(b0 == 0 ) break;
}
for(;i >= 0; --i )
{
d= (d*d)%n;
if(b[i] == 1 )
{
d= (d*a)%n;
}
}
return d;
} int givean(int n)
{
int num[40]={
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
};
unsigned __int64 x=mod_exp(2,num[n-1]-1,1000000007)-1;
return x;
}
int main()
{
unsigned __int64 kk=givean(40);
printf("%d",kk);
return 0;
}
解题完毕!
不可表示的数[x/2] + y + x * y的更多相关文章
- (x&y) + ((x^y)>>1)即x和y的算数平均值
(x&y) + ((x^y)>>1)相当于(x+y)/2 (x&y)+((x^y)>>1),把x和y里对应的每一位(指二进制位)都分成三类,每一类分别计算平均值 ...
- 给定表达式[x/2] + y + x * y, 其中x,y都是正整数。
改进了一下,不过还是要十多秒吧. package com.boco.study; import java.math.BigDecimal; import java.util.Calendar; imp ...
- python 循环高级用法 [expression for x in X [if condition] for y in Y [if condition] ... for n in N [if condition] ]按照从左至右的顺序,分别是外层循环到内层循环
高级语法 除了像上面介绍的 [x ** 2 for x in L] 这种基本语法之外,列表推导式还有一些高级的扩展. 4.1. 带有if语句 我们可以在 for 语句后面跟上一个 if 判断语句,用于 ...
- pageX/Y, offset(), position(), scrollTop(), screenX/Y, clientX/Y, pageX/Y
event.pageX get mouse position Description: The mouse position relative to the left edge of the docu ...
- x+y = ((x&y)<<1) + (x^y) 证明
法一:我们考虑x,y在二进制表示时候,按位相加其中第i位xi+yi = ((xi&yi)<<1) + (xi^yi)其中(xi&yi)<<1表示当xi和yi都是 ...
- 原生js获取鼠标坐标方法全面讲解:clientX/Y,pageX/Y,offsetX/Y,layerX/Y,screenX/Y【转】
关于js鼠标事件综合各大浏览器能获取到坐标的属性总共以下五种 event.clientX/Y event.pageX/Y event.offsetX/Y event.layerX/Y event.sc ...
- clientX/Y,pageX/Y,offsetX/Y,layerX/Y,screenX/Y ,offsetTop,offsetLeft 详解
clientX/Y: clientX/Y获取到的是触发点相对浏览器可视区域左上角距离,不随页面滚动而改变 兼容性:所有浏览器均支持 pageX/Y: pageX/Y获取到的是触发点相对文档区域左上角距 ...
- 关于(x&y)+((x^y)>>1)的探究
今天在程序员面试宝典上看到 int f(int x int y ) { return (x&y)+((x^y)>>1) } f(729,271) 结果为500 从式子中可以看出分为 ...
- 原生js获取鼠标坐标方法全面讲解:clientX/Y,pageX/Y,offsetX/Y,layerX/Y,screenX/Y
关于js鼠标事件综合各大浏览器能获取到坐标的属性总共以下五种 event.clientX/Y event.pageX/Y event.offsetX/Y event.layerX/Y event.sc ...
随机推荐
- BZOJ 1692: [Usaco2007 Dec]队列变换( 贪心 )
数据 n <= 30000 , 然后 O( n² ) 的贪心也过了..... USACO 数据是有多弱啊 = = ( ps : BZOJ 1640 和此题一模一样 , 双倍经验 ) ------ ...
- JUnit4的使用2
package com.imooc.test.aware; import org.junit.Test; import org.junit.runner.RunWith; import org.jun ...
- Xamarin.Android开发实践(三)
原文:Xamarin.Android开发实践(三) 一.前言 用过Android手机的人一定会发现一种现象,当你把一个应用置于后台后,一段时间之后在打开就会发现应用重新打开了,但是之前的相关的数据却没 ...
- 最小生成树Prim算法
文章作者:甘航 文章来源:http://www.cnblogs.com/ganhang-acm/转载请注明,谢谢合作. 由于数据结构老师布置的一道题 ,我看prim算法看了半天还是一知半解. 在浏览 ...
- 2014ACM/ICPC亚洲区鞍山赛区现场赛1009Osu!
鞍山的签到题,求两点之间的距离除以时间的最大值.直接暴力过的. A - Osu! Time Limit:1000MS Memory Limit:262144KB 64bit IO Fo ...
- 九、cocos2dx之Actions
本文由qinning199原创,转载请注明:http://www.cocos2dx.net/?p=86 Action是CCNode对象的一种顺序.这些动作经常改变对象的一些属性,比如位置,旋转,缩放等 ...
- 文件队列 QueueFile
/** * Copyright (C) 2010 Square, Inc. * * Licensed under the Apache License, Version 2.0 (the " ...
- Codeforces Round #198 (Div. 2) 340C
C. Tourist Problem time limit per test 1 second memory limit per test 256 megabytes input standard i ...
- Jquery - checked 全选与取消全选
html: <!DOCTYPE html> <html> <head> <title>节点列表</title> <link rel=& ...
- libev源代码浅析
libev是一个开源的事件驱动库,基于epoll,kqueue等OS提供的基础设施.其以高效出名,它可以将IO事件,定时器,和信号统一起来,统一放在事件处理这一套框架下处理. libev的基本使用方法 ...