• Codefroces 958C2


    转自:https://www.cnblogs.com/widsom/p/8857777.html     略有修改

    题目大意:

    n个数,划分为k段,每一段的和mod p,求出每一段的并相加,求最大是多少

    基本思路:

    区间dp无疑

    dp[i][j] 表示到第i个位置为止,分成j段的最大值

    dp[i][j]=max(dp[i][j],dp[l][j-1]+(sum[i]-sum[l])%p)  0<l<i

    由于n很大,p很小,所以优化一下

    dp[i][j] 表示sum取模p后为i,分成j段的最大值

    dp[i][j] = max(dp[i][j],dp[l][j-1] + (sum[i] - l) % p) 0<= l < p

    代码如下:

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<iostream>
    #include<string>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<set>
    
    using namespace std;
    
    typedef long long ll;
    typedef long long LL;
    typedef pair<int,int> pii;
    const int inf = 0x3f3f3f3f;
    const int maxn = 20000+10;
    const ll mod = 1e9+9;
    
    int dp[110][60];
    int a[maxn];
    int main(){
        int n,k,p;
        scanf("%d%d%d",&n,&k,&p);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            a[i]+=a[i-1];
            a[i]%=p;
        }
        for(int i=0;i<p;i++){
            for(int j=0;j<=k;j++){
                dp[i][j]=-inf;
            }
        }
        dp[0][0]=0;
        for(int i=1;i<=n;i++){
            for(int j=k;j>=1;j--){
                for(int l=0;l<p;l++){
                    dp[a[i]][j]=max(dp[a[i]][j],dp[l][j-1]+(a[i]-l+p)%p);
                }
            }
        }
        printf("%d
    ",dp[a[n]][k]);
        return 0;
    }
    

      

  • 相关阅读:
    线段的类
    计算三角形的类
    关于狗的类
    [poj2234] Matches Game
    bzoj[2655] calc
    拉格朗日插值和牛顿插值 菜鸟教程
    NOI模拟赛(3.15) sequence(序列)
    NOI模拟赛(3.13)Hike (远行)
    二分图讲解
    NOI模拟赛(3.8)Problem B
  • 原文地址:https://www.cnblogs.com/imzscilovecode/p/8889350.html
Copyright © 2020-2023  润新知