1. 程式人生 > 資訊 >比爾·蓋茨:如果疫苗有效,富裕國家最快2021年底恢復正常

比爾·蓋茨:如果疫苗有效,富裕國家最快2021年底恢復正常

波動數列

Description

觀察這個數列:

1 3 0 2 -1 1 -2 ...

這個數列中後一項總是比前一項增加2或者減少3。

棟棟對這種數列很好奇,他想知道長度為 n 和為 s 而且後一項總是比前一項增加a或者減少b的整數數列可能有多少種呢?

Input

輸入的第一行包含四個整數 n s a b,含義如前面說述。

Output

輸出一行,包含一個整數,表示滿足條件的方案數。由於這個數很大,請輸出方案數除以100000007的餘數。

粘一下大佬的程式碼!滾動陣列實在看不懂,但是這個非常可以!

https://blog.csdn.net/SunMoonVocano/article/details/79464889?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param

/*
思路:設第一個元素為a0:若想讓最後和為s
則要滿足 sum = a[0]+a[1]+...+a[n-1] = s
由於a[k] 是由 a[k-1] 通過+a或者-b得到的
所以任何 i < k 若a[i]都會對他產生影響
例如:若每次都是加a操作則a[]的值如下 
a0  a0
a1  a0 + a
a2  a0 + a + a
a3  a0 + a + a + a
..... 
也就是說第一次加a 那麼 sum 就會加上n-1個a
然後依次遞減一個,減b相似
但是不管加a或者減b,總的操作的次數為max = (n-1)*n/2次;
其中+a的次數可能為 0到max任何值。一旦+a的次數確定了不妨設為numa,
 -b的次數隨之確定,又因為 s = N*a0 + numa*a - (max-numa)*b;
 若列舉+a的次數,其中只有a0未知,如果a0有整數解,則滿足,就加上
 該種情況下的方案數。
 
 最後就是計算方案數,一旦numa給定,總的可能的方案有多少呢?
 其實問題一轉化,就變成了求從 1,2... n-1 任意取數,能夠組成numa的
 方案數,設該問題為dp[n-1][numa]; 對於一般的dp[i][j] 表示從1-i中選出
 任意個數,使得和為j對第i個數特殊考慮,就有第i個數存在於j內有dp[i-1][j-i]種
 方案。若不在則有dp[i-1][j]種方案。 
 所以 : dp[i][j] = dp[i-1][j] + dp[i-1][j-i];
 若用滾動陣列,就可省去一維。 
 
*/ #include <iostream> using namespace std; typedef long long ll; const ll mod = 100000007; ll dp[10000006]; int main() { ll n,s,a,b; cin>>n>>s>>a>>b; ll ans = 0; dp[0] = 1; for(ll i = 1; i < n; i++) for(ll j = i*(i+1)/2; j >= i; j--) dp[j]
= (dp[j-i] + dp[j])%mod; for(ll i = 0; i <= (n-1)*n/2; i++) { ll tmp = s + i*a - ((n-1)*n/2 - i) * b; if(tmp % n == 0) ans = (ans+dp[i])%mod; } cout << ans <<endl; return 0; }