給定表示式[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,...