• Codeforces 958C3


    转自:http://www.cnblogs.com/widsom/p/8863005.html

    题目大意:

    比起Encryption 中级版,把n的范围扩大到 500000,k,p范围都在100以内,然后让你求最小值

    基本思路:

    记sum[i]表示0 - i 的和对 p 取模的值。

    1.如果k * p > n,那么与C2的做法一致,O(k*p*n)复杂度低于1e8。

    2.如果k * p <= n

    那么根据抽屉原理,必有至少k个sum[i]相同,

    那么任意取k - 1个相同的 sum[i],记它们的下标为 l1,l2,......,lk-1 ,那么显然区间[l+ 1, li+1](1<=i<k-1)的贡献为0

    有贡献的区间只有[1,l1]和[lk-1 + 1,n]由于两个区间的贡献加起来小于2 * (p - 1) ,所以最后的答案要么为 sum[n],要么为 sum[n] + p

    那么怎么判断是前者还是后者呢?

    只要判断在sum中能不能找到一个以sum[n]结尾的长度为k的非严格上升子序列就可以了

    如果能找到就是sum[n],否则就是 sum[n] + p

    LIS的复杂度O(nlogn)

    注意:

    1)关于第二层循环j的循环方向,反方向就不对了,可以仔细思考一下

    关于dp中for循环的方向问题,摘自知乎艾庆兴的回答:

    动态规划随便怎么实现都可以,只要把握一个原则,当你计算dp i的时候,一定要保证你用到的那些全部都已经被算出来了,

    比如区间dp,一般大区间的dp值由小区间算出来,所以你只要保证循环的时候,算每一个大区间之前,小区间都被算出来,就可以

    #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 = 500000+10;
    const ll mod = 1e9+9;
    
    int dp[110][110];
    int _dp[maxn];
    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;
        }
        if(k*p>n){
            memset(dp,inf,sizeof(dp));
            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]=min(dp[a[i]][j],dp[l][j-1]+(a[i]-l+p)%p);
                    }
                }
            }
            printf("%d
    ",dp[a[n]][k]);
        }else{
            memset(_dp,inf,sizeof(_dp));
            for(int i=1;i<=n-1;i++){
                *upper_bound(_dp+1,_dp+n,a[i])=a[i];
            }
            if(_dp[k-1]<=a[n]){
                printf("%d
    ",a[n]);
            }else{
                printf("%d
    ",a[n]+p);
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    出于安全考虑,office outlook禁止对潜在不安全因素的附件访问,如何解决
    70级圣骑士OK了,纪念下先!
    03.配置putty连接Linux系统,并实现中英文输入输出;配置vnc服务器
    想了解你好有的装备及属性吗,副本及飞行点的位置吗?简单!
    Windows Server 2008 下载、安装、激活
    同事的U盘写保护了!
    重新开始核心编程,Windows的开始
    如何知道某PC接入到交换机的哪个端口上
    DK装备获取线路总结
    Windows Server 2008 评估时间延期
  • 原文地址:https://www.cnblogs.com/imzscilovecode/p/8892777.html
Copyright © 2020-2023  润新知