給定乙個長度為 n
'>n
的序列 a
'>a
,求 a
'>a
有多少個長度為 m
'>m
的嚴格遞增子串行。
輸入格式
第一行包含整數 t
'>t
t,表示共有 t
'>
t 組測試資料。
每組資料,第一行包含兩個整數 n
'>
n 和 m
'>
m。第二行包含 n
'>
n 個整數,表示完整的序列 a
'>
a。輸出格式
每組資料輸出乙個結果,每個結果佔一行。
輸出格式為case #x: y
,x
'>x
為資料組別序號,從 1
'>1
1 開始,y
'>y
y 為結果。
由於答案可能很大,請你輸出對 109+
7'>1e9+7
取模後的結果。
資料範圍1≤
t≤100'>1≤t≤1001≤
m≤n≤
1000
'>1≤m≤n≤1000∑i
=1tn
i×mi
≤107'>∑ti=1ni×mi≤1e7
序列中的整數的絕對值不超過10
9'>1e9
。輸入樣例:
2
3 21 2 3
3 23 2 1
輸出樣例:case #1: 3
case #2: 0
f[maxn][maxn];//以第i個結尾時,有j個遞增的方案數
優化之前的**時這樣的:
#include#include#include
using
namespace
std;
const
int maxn=1e3+100
;const
int mod=1e9+7
;int
a[maxn],t;
int f[maxn][maxn];//
以第i個結尾時,有j個遞增的方案書
intn,m;
intmain()
f[1][1]=1
;
for(int i=1;i<=n;i++)
for(int i=2;i<=n;i++)
f[i][j+1]%=mod;} }
}int ans=0
;
for(int i=1;i<=n;i++)
printf(
"case #%d: %d\n
",++kase,ans);
} }
然後可以用線段樹或者樹狀陣列優化掉一維
#include#include#include
typedef
long
long
ll;using
namespace
std;
const
int maxn=1e3+100
;const
int mod=1e9+7
;int
a[maxn],t;
int f[maxn][maxn];//
以第i個結尾時,有j個遞增的方案數
intn,m;
int cnt=0
; int
c[maxn];
intnum[maxn];
int lowbit(int
x)void add(int x,intk)}
int getsum(int
x)
return
ans;
}int
main()
sort(num+1,num+cnt+1
); cnt=unique(num+1,num+cnt+1)-(num+1
);
for(int i=1;i<=n;i++)
for(int i=1;i<=n;i++)
for(int j=2;j<=m;j++)
for(int i=1;i<=n;i++)
}int ans=0
;
for(int i=1;i<=n;i++)
printf(
"case #%d: %d\n
", ++kase,ans);
}}
數字DP 樹狀陣列
考慮如何計算f l r f l r 很顯然,可以分別計算l,r l,r 的二進位制中1的個數,然後減去 最大公共字首的1的個數 2。考慮如何統計每一對l,r l,r 的最大字首中1的個數,可以用數字dp。記f i j 1 0 1 0 f i j 1 0 1 0 表示前i i 位,最大公共字首中1的個...
hdu 2227 樹狀陣列 dp
題意是求乙個數列的不遞減的子串行的個數 很顯然,如果只用dp來做的話時間是o n n 因為dp i 為前i個數可能的方案,則狀態轉移方程為dp i sum dp j j 先對num按數來進行排序,這道題因為資料較大 用到了離散化 因為更新是是按原序更新的,及i之前的num j 一定比num i 小,...
hdu5489 樹狀陣列 dp
2015 10 06 21 49 54 這題說的是個給了乙個陣列,然後刪除任意起點的乙個連續的l個數,然後求最長遞增子串行 是遞增,不是非遞減 用乙個樹狀陣列維護一下就ok了 include include include include include using namespace std co...