波動數列 數論推導,dp

2021-10-19 23:35:40 字數 1487 閱讀 1273

題目鏈結

觀察這個數列:

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,含義如前面所述。輸出格...