庞果答题:亿阳信通:不可表示的数 的一个人见解(8-13第二次更新。)
原題:
給定表達式[x/2] + y + x * y, 其中x,y都是正整數(shù)。其中的中括號表示下取整,例如[3/2] = 1 , [5/2] ?= 2。
有些正整數(shù)可以用上述表達式表達出來,
例如正整數(shù)2,當(dāng)取x = y = 1時,可以把2表達出來 ( 解釋下:當(dāng)x=y=1時, [x / 2] + y + x * y = [1 / 2] + 1 + 1 * 1 = 0+1+1 = 2 );
?有些數(shù)可以有多種方式表達,例如13可以由 x = 2 y = 4 以及x = 3 y = 3來表示;?
有些數(shù)無法用這個表達式表達出來,比如3。
?從1開始第n個不能用這個表達式表示出來的數(shù),我們叫做an,例如a1=1 a2=3,給定n,求an。?
輸入:n值 1<=n<=40 輸出:an % 1000000007的結(jié)果(因為結(jié)果較大,輸出an %1000000007的結(jié)果)。
個人分析:
表達式相當(dāng)于?(x+1)*y+[x/2]
x=1...n 時,表達式分別為:
2*y ?3*y+1 ?4*y+1 ?5*y+2 6*y+2 ?7*y+3 8*y+3 9y+4 10y+4 11y+5 12y+5 ...
這時我們分析:
第一個表達式為 偶數(shù)
第二個表達式為 an-1 整除4=0;
第三個表達式為 an-1?整除5=0;
。。。
由此類推
我們在判斷 an 這個數(shù)是否為 不可表達的數(shù)時,應(yīng)用如下判斷
an%2!=0
如果an>1那么 (an-1)%3!=0 并且 因為x=4時,表達式相同 我們也應(yīng)判斷?(an-1)%4!=0?
如果an>2那么 (an-2)%5!=0 并且 因為x=4時,表達式相同 我們也應(yīng)判斷?(an-2)%6!=0?
.....
那么合適結(jié)束呢?判斷到an/2,x固定時第一個表達式為最小值
那么我們的判斷函數(shù)應(yīng)為:
public static int givean(int n){if (n < 1 || n > 40)return -1;double result = 0;int countN = 0;while (countN != n){result += 1;//* 以上相當(dāng)于 (x+1)*y+[x/2]// * 表達式為:x=1...n : 2*y 3*y+1 4*y+1 5*y+2 6*y+2 7*y+3 8*y+3 9y+4 10y+4 11y+5 12y+5 13+6 14+6 15+7 16+7 17+8 18+8 // * 在這里我們可以看出規(guī)律,// 當(dāng)an=3時 我們只需判斷 // 1 an-2是否能被5,6整除 // 2 an-1 是否能被3,4整除// 3 an 是否能被2整除//.....如果符合上述條件則可以表達,如果不符合則不可表達bool issuit = false;for (double i = 0; i < result/2; i++){double x = Math.Round(i*2, 0)+1;if (Math.Abs(x - 1) > 0.00001d){//eg: i=1 x=3 x1=4; i=2 x=5 x1=6;i=3 x=7 x1=8double x1 = x + 1;if (Math.Abs((result - i) % x - 0f) < 0.00001d || Math.Abs((result - i) % x1 - 0f) < 0.00001d){issuit = true;break;}}else{if (Math.Abs(result % 2 - 0) < 0.00001d) //x=1 表達式為2*y 偶數(shù)全部可以表達{issuit = true;break;}}}//if(!issuit)countN++;}return (int) (result % 1000000007);}
得到的結(jié)果為: a1=1 ,a2=3,a3=15,a4=63,a5=4095,a6=65535,a7=262143,a8=...
計算a8就要很長時間了。
這個解決方案是否正確尚未可知,我提交上去代碼后卻提示:
另外再提交C#代碼時,注意將類名改為其他,他與主函數(shù)重名會報錯。。。
另外不知道龐果檢測代碼是如何進行的,判斷正確與否是怎么個機制,應(yīng)該是提取方法驗證結(jié)果與時間吧,
挺有意思的,希望懂行的多交流交流。
看了一下,已經(jīng)有16個大牛做出來了。
不過,這么多的問題沒有答案什么的嘛,或者交流的地方。。。。
2013年8月13日6:38:20早晨 更新?
晚上睡覺的時候想了想,只能優(yōu)化算法了,目標(biāo) 取a40 ?3s內(nèi)。。。
再循環(huán)的時候可以減輕一些壓力,首先【 前取整】 代表有連續(xù)的兩個數(shù)相等,所以我們循環(huán)的步長可以是2
修改代碼如下:
public static int givean(int n){Stopwatch stp=new Stopwatch();stp.Start();if (n < 1 || n > 40)return -1;if (n == 1)return 1;double result = 1;int countN = 1;while (countN != n){//x=1 表達式為2*y 偶數(shù)全部可以表達 所以我們支取基數(shù)result += 2;//* 以上相當(dāng)于 (x+1)*y+[x/2]// * 表達式為:x=1...n : 2*y 3*y+1 4*y+1 5*y+2 6*y+2 7*y+3 8*y+3 9y+4 10y+4 11y+5 12y+5 13+6 14+6 15+7 16+7 17+8 18+8 // * 在這里我們可以看出規(guī)律,// 當(dāng)an=3時 我們只需判斷 // 1 an-2是否能被5,6整除 // 2 an-1 是否能被3,4整除// 3 an 是否能被2整除//.....如果符合上述條件則可以表達,如果不符合則不可表達bool issuit = false;//y=1,2....n : 1+x+[x/2] 2+2x+[x/2] 3+3x+[x/2] ...n+nx+a//x的值取y=1時 的最大值為double limit = result - 1;//x=2,3...時的表達式判斷[2/2]=[3/2] [x/2]=[x+1/2]所以x的步長為2,一次判斷兩個for (double x = 2; x <= limit; x += 2){////[x/2]double yushu = Convert.ToInt64(x/2);double a = x + 1;//系數(shù)////limit = result - yushu - 1;//if (Math.Abs((result - yushu) % a - 0f) < 0.00001d ||Math.Abs((result - yushu) % (a+1) - 0f) < 0.00001d){issuit = true;break;}}if (!issuit){countN++;Console.WriteLine("N=" + countN + " an=" + result);}}stp.Stop();TimeSpan ts = stp.Elapsed;string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10);Console.WriteLine("Time taken?:?{0}", elapsedTime);return (int) (result % 1000000007);}
運行的結(jié)果是:
N=2 ?an=3
N=3 ?an=15
N=4 ?an=63
N=5 ?an=4095
N=6 ?an=65535
N=7 ?an=262143
Time taken?:?00:00:00.11
計算n=8時 需要5分多鐘。。。。太讓人郁悶了。
開來還是有優(yōu)化的地方。。。。
2013年8月13日8:17:35 第二次更新
重新更改了一下:
這下取n=8 控制到5分鐘以內(nèi)了,代碼如下:
public static int givean(int n){Stopwatch stp=new Stopwatch();stp.Start();if (n < 1 || n > 40)return -1;if (n == 1)return 1;double result = 1;int countN = 1;while (countN != n){//x=1 表達式為2*y 偶數(shù)全部可以表達 所以我們支取基數(shù)result += 2;//* 以上相當(dāng)于 (x+1)*y+[x/2]// * 表達式為:x=1...n : 2*y 3*y+1 4*y+1 5*y+2 6*y+2 7*y+3 8*y+3 9y+4 10y+4 11y+5 12y+5 13+6 14+6 15+7 16+7 17+8 18+8 // 2y+0 3y+1 4y+1 5y+2 6y+2 7y+3 8y+3 9y+4 10y+4//11y+5 12y+5 13y+6 14y+6 15y+7 16y+7 18y+8 19y+8 20y+9 21y+9////eg:result=5 5*2/3=3 (3+1)*1+1=5long tmpx = Convert.ToInt64(result*2/3);if ((tmpx + 1 + Convert.ToInt64(tmpx / 2)) == Convert.ToInt64(result))continue;//// * 在這里我們可以看出規(guī)律,// 當(dāng)an=3時 我們只需判斷 // 1 an-2是否能被5,6整除 // 2 an-1 是否能被3,4整除//.....如果符合上述條件則可以表達,如果不符合則不可表達bool issuit = false;//y=1,2....n : 1+x+[x/2] 2+2x+[x/2] 3+3x+[x/2] ...n+nx+a//x的值取y=1時 的最大值為double limit = result - 1;//x=2,3...時的表達式判斷[2/2]=[3/2] [x/2]=[x+1/2]所以x的步長為2,一次判斷兩個for (double x = 2; x <= tmpx; x += 2){////此x值得表達式為 a * y + yushudouble yushu = Convert.ToInt64(x/2);double a = x + 1; //系數(shù)double a2 = x + 2;////此時,如果系數(shù)與加數(shù)同為偶數(shù)時 可以不用判斷//if (Math.Abs(yushu % 2 - 0) > 0.00001d || Math.Abs(a % 2 - 0) > 0.00001d){if (Math.Abs((result - yushu)%a - 0f) < 0.00001d){issuit = true;//Console.WriteLine(x+"");break;}}// Math.Abs((result - yushu)%(a + 1) - 0f) < 0.00001dif (Math.Abs(yushu % 2 - 0) > 0.00001d || Math.Abs(a2 % 2 - 0) > 0.00001d){if (Math.Abs((result - yushu) % a2 - 0f) < 0.00001d){issuit = true;//Console.WriteLine(x+1 + "");break;}}}if (!issuit){countN++;Console.WriteLine("N=" + countN + " an=" + result);}}stp.Stop();TimeSpan ts = stp.Elapsed;string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10);Console.WriteLine("Time taken?:?{0}", elapsedTime);return (int) (result % 1000000007);}
想了一下,如果數(shù)據(jù)變大時比如10000001時,要驗證的太多了,也即循環(huán)耗費時間太長了,
看來規(guī)律總結(jié)的不到位啊。
2013年8月14日15:05:09更新
看了http://blog.csdn.net/chengyxc/article/details/9958035?他這個算法似乎是對的,
符合的條件:n具有2^m-1的形式,并且,2n+1必定是個素數(shù),這樣的數(shù)才是不可能數(shù)
跟著更新了下算法。
但是 好像還是不能很好的實現(xiàn)。時間是個大問題,算到第21個數(shù)了,用時大約10s了。
肯定超限了。
算法如下:
Stopwatch stp=new Stopwatch();stp.Start();long inf = 140000000;// int.MaxValue;// 264800000;// 2147483637; //List<int> prime = new List<int>();int[] prime = new int[inf];prime[0] = prime[1] = 0;for (int i = 2; i < inf; ++i)prime[i] = 1;for (int i = 4; i < inf; i += 2)prime[i] = 0;double t = Math.Sqrt(inf);for (int i = 3; i <= t; i += 2){if (prime[i]>0){int k = i * i, p = i + i;for (int j = k; j < inf; j += p){prime[j] = 0;//if ((j - 1)%2 == 0)// Console.WriteLine("j="+j+" "+(j - 1) /2 + "");}}}//以上得到了 1 -- inf 范圍 中的所有素數(shù),在素數(shù)中判斷條件int count = 1;for (long i = 0; i < prime.LongLength; i++){if (prime[i] != 0){if ((i - 1)%2 == 0){//符合2n+1為素數(shù)double n = (i - 1)/2;if (n < 3)continue;//符合2^M-1double a = Math.Log(n + 1, 2); // Math.Log(2, n + 1);double b = (a - Convert.ToInt64(a));if (a != double.NaN && a > 1 && Math.Abs(a - Convert.ToInt64(a)) < 0.000001d){count++;//Console.WriteLine(string.Format("n={0} an={1}",count,n));}}}}stp.Stop();Console.WriteLine(stp.ElapsedMilliseconds/1000d+"S");//輸出結(jié)果為:
n=2 an=3
n=3 an=15
n=4 an=63
n=5 an=4095
n=6 an=65535
n=7 an=262143
n=8 an=2097150
n=9 an=8388606
n=10 an=33554409
n=11 an=33554418
n=12 an=33554429
n=13 an=33554439
n=14 an=67108824
n=15 an=67108844
n=16 an=67108878
n=17 an=67108886
n=18 an=67108889
n=19 an=67108890
n=20 an=67108899
n=21 an=67108901
9.854S
我的是32位系統(tǒng),數(shù)組最大長度只能設(shè)為:264800000 再長就報超出內(nèi)存了。也不知道是不是系統(tǒng)的問題。64位系統(tǒng)的驗證一下吧。
總結(jié)
以上是生活随笔為你收集整理的庞果答题:亿阳信通:不可表示的数 的一个人见解(8-13第二次更新。)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小程序实现城市搜索功能
- 下一篇: 四级地址插件升级改造(京东商城地址选择插