題目鏈結
觀察這個數列:
1 3 0 2 -1 1 -2 …
這個數列中後一項總是比前一項增加2或者減少3,且每一項都為整數。
棟棟對這種數列很好奇,他想知道長度為 n 和為 s 而且後一項總是比前一項增加 a 或者減少 b 的整數數列可能有多少種呢?
共一行,包含四個整數 n,s,a,b,含義如前面所述。
共一行,包含乙個整數,表示滿足條件的方案數。
由於這個數很大,請輸出方案數除以 100000007 的餘數。
資料範圍
1≤n≤1000,
−109≤s≤109,
1≤a,b≤106
4 10 2 3
2樣例解釋
兩個滿足條件的數列分別是2 4 1 3和7 4 1 -2。
和s == x + (x+d1)+(x+d1+d2)+…+(x+d1+…dn-1) 其中d∈;
整理式子得 s == n * x + (n-1) * d1 +(n-2) * d2+…+dn-1;
s給了,n給了,a b給了所以d也是知道的,那麼就要求x的可能數了,我們繼續轉化
x == /n;
那麼x是整數,所以 / n得到的是整數就意味著
s -((n-1) * d1 +(n-2) * d2+…+dn-1)是n的倍數,所以兩個分式餘n的餘數是要相同的,這樣可以使n整除
s%n是直接知道的,那麼我們就要求((n-1) * d1 +(n-2)*d2+…+dn-1)%n了.這些都是一步一步來的,所以我們用動態規劃的思想來進行
dp[i][j]表示前i項的和餘n的餘數為j
我們定義sum為前i-1項的和,第i項為i * a
我們能得到 (sum+(i * a))%n == j .j是小於n的所以j%n == j這樣我們轉換為同餘方程
同餘方程是可以直接加減的
(sum+(i * a))%n == j%n =>sum%n == (j-(i * a))%n.
所以我們能得到狀態轉移方程dp[i][j]=dp[i-1][(j-(i * a))%n]+dp[i-1][(j+(i * b))%n];
其中是有負數的所以我們要保證餘數為正,所以加上乙個方程就行了(a%b+b)%b就可以保證餘數為正
#include
#include
#include
#include
using namespace std;
const
int maxn=
1e3+5;
const
int mod=
100000007
;int dp[maxn]
[maxn]
;int n,s,a,b;
intget_mod
(int a,
int b)
intmain()
} cout<[get_mod
(s,n)
]
}
E波動數列(dp)
由於這道題目的資料量比較大,採用dp處理的時候,還涉及到滾輪陣列。關於滾輪陣列的講解 題意分析 include include define maxn 1100 define mod 100000007 using namespace std typedef long long ll ll n,s,...
波動數列 DP 組合
觀察這個數列 1 3 0 2 1 1 2 這個數列中後一項總是比前一項增加2或者減少3,且每一項都為整數。棟棟對這種數列很好奇,他想知道長度為 n 和為 s 而且後一項總是比前一項增加 a 或者減少 b 的整數數列可能有多少種呢?輸入格式 共一行,包含四個整數 n,s,a,b,含義如前面所述。輸出格...
AcWing 1214 波動數列(推柿子 DP)
觀察這個數列 1 3 0 2 1 1 2 這個數列中後一項總是比前一項增加2或者減少3,且每一項都為整數。棟棟對這種數列很好奇,他想知道長度為 n 和為 s 而且後一項總是比前一項增加 a 或者減少 b 的整數數列可能有多少種呢?輸入格式 共一行,包含四個整數 n,s,a,b,含義如前面所述。輸出格...