1 条题解

  • 0
    @ 2025-8-24 23:18:04

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar JHPOTATO
    那也请不要忘记 落泪的眼睛 曾动容的心情

    搬运于2025-08-24 23:18:04,当前版本为作者最后更新于2025-06-14 20:05:10,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    存在一个显然的性质:对于任意一个区间 [l,r]\left [ l,r \right ] ,设用其中元素至多能参加 xx 场婚礼,那么对于任意 yxy \le x,都可以找到一种合法的方案。

    所以我们可以统计每个区间能参加婚礼的最大次数,并借助这个判定一个区间能否完全利用。

    转移是简易的,因为只关心最大次数,所以只需要枚举断点,判断剩下元素总和对 dd 取模是否为 rr 即可。

    为了判定简便,可以事先预处理达到每个余数至少要举办几场婚礼。

    其余细节可以见代码。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    template <typename T>
    void in(T &x){
    	char c=getchar(), f=1;
    	while ((c<'0' || c>'9') && c!='-') c=getchar();
    	if (c=='-') f=-1, c=getchar();
    	for (x=0; c>='0' && c<='9'; c=getchar())
    		x=x*10+c-'0';
    	x*=f;
    }
    const int N=505;
    int n,d,r,al,dp[N][N];
    long long s[N],f[N][N];
    unordered_map<int,int>p;
    int main(){
    	in(n);in(d);in(r);
    	for(int i=1;i<=n;i++){
    		al+=r;if(al>=d)al-=d;
    		if(p.count(al))break;
    		p[al]=i;
    	}
    	for(int i=1;i<=n;i++){
    		in(s[i]);
    		if(s[i]%d==r)dp[i][i]=1,f[i][i]=s[i]/d;
    		s[i]+=s[i-1];
    	}
    	for(int l=1;l<n;l++){
    		for(int i=n-l;i;i--){
    			int j=i+l,mx=0;
    			for(int k=i;k<j;k++){
    				f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]);
    				mx=max(mx,dp[i][k]+dp[k+1][j]);
    			}
    			long long xx=(s[j]-s[i-1])%d;
    			if(p.count(xx)&&p[xx]==mx+1)mx++;//如果res=0似乎会使mx变大(用0张巻白吃?)
    			//但res=0如果出现,就一定是最后一项,也就是所有可达余数都已经能被计算出来了,多统计无影响
    			dp[i][j]=mx;
    			if(p.count(xx)&&mx>=p[xx])f[i][j]=max(f[i][j],(s[j]-s[i-1]-p[xx]*1ll*r)/d);
    		}
    	}
    	cout<<f[1][n];
    	return 0;
    }
    /*
    dp[i][j]->区间[i,j]至多能参加几场婚礼
    f[i][j]->区间[i,j]的答案
    显然,只要需求可达且不超过dp[i][j],都能凑出来
    */
    
    • 1

    信息

    ID
    12516
    时间
    2000ms
    内存
    2048MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者