K序列(子序列的和能夠被k整除、DP)


 

鏈接:https://ac.nowcoder.com/acm/contest/91/L?&headNav=www
來源:牛客網

時間限制:C/C++ 1秒,其他語言2秒
空間限制: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 }

 

 

 

 

 

 

 

 

 

-


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM