码迷,mamicode.com
首页 > 其他好文 > 详细

第三届中国计量大学ACM程序设计竞赛个人赛 C

时间:2020-06-04 15:36:47      阅读:162      评论:0      收藏:0      [点我收藏+]

标签:端点   表示   拆分   bit   while   cout   元素   前缀和   code   

Pinch Pinch Pinch

传送门

题意:给你一个整数N,定义一次操作为将这个数字切割为一个等差数列,如果有多种方案,只能选择元素最多的方式。切割之后的数据仍然能继续切割,但是每次只能选择一个元素进行切割,问最多能进行多少次操作?

题解:简单dp,首先需要考虑对于一个数字而言,切割得最多的方法的左端点和右端点,这个可以通过倒序暴力扫左端点得到(由调和级数可知复杂度是\(O(nlog(n))\))。其次,我们需要维护一个前缀和,表示[1,n]中,每一个数的可以拆分的次数,然后转移就可以了,具体见代码。

#include<bits/stdc++.h>

using namespace std;

inline int read(){
    int res=0, f=1;char ch=getchar();
    while(ch<‘0‘|ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){res=res*10+ch-‘0‘;ch=getchar();}
    return res*f;
}

const int N = 1000005;

const int MOD = 1000000007;

template<typename T>
void chmin(T& a, T b){if(a>b)a=b;}

template<typename T>
void chmax(T& a, T b){if(b>a)a=b;}

int L[N],R[N],sum[N],dp[N];

int main(){
    int t=read();

    int n=1000000;
    for(int i=n;i>=1;--i){
        int tot=i;
        for(int j=i+1;j<=n;++j){
            tot+=j;
            if(tot>n)break;
            L[tot]=i,R[tot]=j;
        }
    }

    for(int i=1;i<=n;++i){
        if(L[i])chmax(dp[i],sum[R[i]]-sum[L[i]-1]+1);
        sum[i]=sum[i-1]+dp[i];
    }

    while(t--){
        int x=read();
        cout<<dp[x]<<endl;
    }



    return 0;
}

第三届中国计量大学ACM程序设计竞赛个人赛 C

标签:端点   表示   拆分   bit   while   cout   元素   前缀和   code   

原文地址:https://www.cnblogs.com/JohnRan/p/13043681.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!