鏈接:https://ac.nowcoder.com/acm/contest/91/L?&headNav=www
來源:牛客網
時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 131072K,其他語言262144K
64bit IO Format: %lld
空間限制:C/C++ 131072K,其他語言262144K
64bit IO Format: %lld
題目描述
給一個數組 a,長度為 n,若某個子序列中的和為 K 的倍數,那么這個序列被稱為“K 序列”。現在要你對數組 a 求出最長的子序列的長度,滿足這個序列是 K 序列。
輸入描述:
第一行為兩個整數 n, K, 以空格分隔,第二行為 n 個整數,表示 a[1] ∼ a[n],1 ≤ n ≤ 105, 1 ≤ a[i] ≤ 109, 1 ≤ nK ≤ 107
輸出描述:
輸出一個整數表示最長子序列的長度 m
示例1
輸入
7 5 10 3 4 2 2 9 8
輸出
6
dp[j]結果為j的最大長度,temp保存上一次的dp結果,相當於上一次的dp數組
我們對於每個a[ i ],用上一次的dp[ j ]也就是temp[ j ]加上a[ i ]再mod k,去更新dp[(j+a[ i ])%k],然后再維護temp的最大性即可
轉移的條件:如果temp[j]==0就意味着之前都沒有一個結果是j的,那么就不應該在j的基礎上去更新其他dp了(j=0的時候就不用管temp[j]是否為0了)。
1 #include <bits/stdc++.h> 2 typedef long long LL; 3 #define pb push_back 4 const int INF = 0x3f3f3f3f; 5 const double eps = 1e-8; 6 const int mod = 1e9+7; 7 const int maxn = 1e5+10; 8 const int maxk = 1e7+10; 9 using namespace std; 10 11 int a[maxn]; 12 int dp[maxk];//dp[j]結果為j的最大長度 13 int temp[maxk];//保存上一次的dp結果,相當於上一次的dp數組 14 15 int main() 16 { 17 #ifdef DEBUG 18 freopen("sample.txt","r",stdin); //freopen("data.out", "w", stdout); 19 #endif 20 21 int n,k; 22 scanf("%d %d",&n,&k); 23 for(int i=1;i<=n;i++) 24 scanf("%d",&a[i]); 25 for(int i=1;i<=n;i++) 26 { 27 for(int j=0;j<k;j++)//用上一次的dp[j]也就是temp[j]去更新dp[(j+a[i])%k] 28 { 29 if(j==0||temp[j]!=0) 30 dp[(j+a[i])%k] = temp[j]+1; 31 } 32 for(int j=0;j<k;j++)//由於上面dp[j]的值可能更新小,所以讓temp始終保持最大 33 temp[j] = max(temp[j],dp[j]); 34 } 35 printf("%d\n",dp[0]); 36 37 return 0; 38 }
-