n確認序列長度,m確定最後乙個數。還有乙個要求是(從提示可以明顯看出),每兩個數,後者要能整除前者,比如[1,3,3]中,【1,3】要3能整除1,【3,3】要3能整除3。
如果n=1那麼只有一種情況。
如果n>1,那麼有遞迴式,dp[n,m] = sum( dp[n-1][x] )。x為n所有可能的因數。
根據上圖來看,比如找【3,4】,4的因數有1,2,4,那麼就等於【2,1】【2,2】【2,4】的個數相加,如果看每個元素儲存的序列,那就是【2,1】【2,2】【2,4】裡面的各個序列後面再加個4。
解釋一下這個遞迴式:
1.第n個數字是m,第n-1個必須是m的因數x
2.已經確定了第n個數字,剩餘的前n-1個數的情況,已經被所有的dp[n-1][x]存起來了(因為找的是x,x又是m的因數,所以就可以滿足第n-1個是m的因數)
3.根據這樣分析遞推,那麼又可以得到第n-2個又是第n-1的因數。
#include
using namespace std;
const
int mod =
1e9+7;
typedef
long
long ll;
ll dp[
1005][
1005];
intmain()
}if(tmp * tmp == j)}}
int n, m;
while
(cin >> n >> m)
return0;
}
**來自牛客網大佬@hankin,先在此鳴謝。解釋一下那個平方根,因為乙個數的因數是成對出現的,我們只需要求到1到平方根的因數就行,另一半因數用原數除以因數就能得到。比如10,平方根是3,遍歷1,2,3。1是因數,10/1也是因數;2是因數,10/2也是因數。3不是因數。
修改成py**,使用滾動陣列,降低空間複雜度。
import math
n,m =
map(
int,
input()
.split())
mod =
10**9+
7dp =[[
0]*(m+1)
,[1]
*(m+1)
]for i in
range(2
,n+1):
lastrow =
(i-1)%
2 row = i %
2for j in
range(1
,m+1):
temp =
int(math.sqrt(j)
) dp[row]
[j]=
0for k in
range(1
,temp+1)
:if j%k ==0:
dp[row]
[j]+= dp[lastrow]
[k] dp[row]
[j]%= mod
dp[row]
[j]+= dp[lastrow]
[j//k]
dp[row]
[j]%= mod
if temp*temp == j:
dp[row]
[j]-= dp[lastrow]
[temp]
dp[row]
[j]%= mod
print
(dp[n%2]
[m])
可以發現陣列是重複利用的,但必須是[[0]*(m+1),[1]*(m+1)]
,不能只是[1]*(m+1)
,因為如果這樣,算dp[n,m] = sum( dp[n-1][x] )時,較小的x對應的dp[n-1][x]
會被更新為dp[n][x]
,這樣等算到較大的x對應的dp[n][x]
時,需要用到較小的x對應的dp[n-1][x]
,但此時較小的x對應的dp[n-1][x]
已經被更新為dp[n][x]
,這樣算出來就不對了。 2015筆試記錄
0916去哪兒網 1.removeelement arr,index 這麼簡單的題竟然寫錯了,把splice方法的返回值記錯了,splice返回的是刪除的元素陣列!2.陣列亂序問題 以前看過fisher yates的洗牌演算法,所以有點思路,但還是有細節錯誤 math.random 的範圍是 0,1...
中興2016筆試
簡答題 1 ip位址和mac位址有什麼區別?為什麼要有這兩種位址?對於ip位址,相信大家都很熟悉,即指使用tcp ip協議指定給主機的32位位址。ip位址由用點分隔開的4個8八位組構成,如192.168.0.1就是乙個ip位址,這種寫法叫點分十進位制格式。ip位址由網路位址和主機位址兩部分組成,分配...
2019 6 5筆試回顧
1.union和union all的區別 答案來自w3cshool select city,country from customers union select city,country from suppliers 上面的語句返回t 消費者和t 商的城市,國家。set 無重複 注 武漢,中國 和...