不可表示的數(龐果網)完全解答

2021-06-18 02:38:44 字數 2688 閱讀 2346

給定表示式[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 int givean(int n) 

}//當count不可表示

if (m == 1)

i++;

count += 2;

} while (i < n);

return (count - 2)% 1000000007;

}int main()

但是當我們執行時發現得到a1 = 1, a2 = 3, a3 = 15, a4 = 63, a5 = 4095, a6 = 65535, a7 = 262143很快。

當n = 8,算出(a8 = 1073741823) % 1000000007= 73741816

卻要兩、三分鐘。所以此方法理論是對的,卻不合適。

相信很多人像我一樣在,接下來是對上面演算法進行各種優化,加大count的增補量、減小x的迴圈範圍等等,但作用對於求解a40來說將微乎其微。

鬱悶,疑惑之中在網上大查一番終於有所眉目,將借鑑整理如下。

方法二

下面仁兄部落格將對此方法用到的數學方法,進行詳細說明:

相信看完以上部落格我們知道:若乙個數2^(m + 1)- 1是素數,則2^m - 1即為乙個不可表示的數(m >= 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,

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 int givean(int n)

; int num = p[n-1] - 1, s = 1, i;

for (i = 1; i <= num; i++)

return s-1;

}int main()

51goc 637 可表示的數 題解

有n個整數從左到右排成一行,如果某個數等於它前面的2個數的和,就稱這個數是可以表示的數。問給定的數列裡有多少個數是可以表示的數。第一行1個整數n,表示數列有多少個整數。1 n 10000。第二行n個正整數,每個正整數不超過10000。乙個整數,有多少可表示的數。637.可表示的數 本題讓我們輸入乙個...

龐果英雄會 子串行的個數

本題同樣來自caopengcs,只要你有興趣,每個人都可以出題 出題入口在主頁右側邊欄 貢獻題目 我要發布 內 以下是題目詳情 要求輸出a的不同子串行的數量。輸入 輸出 剛開始的時候我總想著直接去算排列組合,然後根據容斥原理把重複的去掉,從而得到結果,後來發現這樣不是不行,要考慮的東西實在是太多了,...

挑戰龐果英雄會之子串行的個數

題目詳情 本題同樣來自caopengcs,只要你有興趣,每個人都可以出題 出題入口在主頁右側邊欄 貢獻題目 我要發布 內 以下是題目詳情 子串行的定義 對於乙個序列a a 1 a 2 a n 則非空序列a a p1 a p2 a pm 為a的乙個子串行,其中1 p1例如 4,14,2,3和14,1,...