[AGC041D] Problem Scores 题解

题目链接

点击打开链接

题目解法

首先,思考一些性质
不难发现,\(k=\lfloor \frac{n-1}{2}\rfloor\) 时是最优的
现在的限制变成了 \(a_i\le n,\;a_i\le a_{i+1},\;\sum\limits_{i=1}^{k+1}a_i\ge \sum\limits_{i=n-k+1}^n a_i\)
这个东西我一直不会 \(n^2\) 维护
看了 \(kubic\) 的题解,我恍然大悟
\(trick\):初始令 \(a_i=n\),每次对一个前缀 \(-1\),那么每一个合法的 \(a\) 序列都可以通过这样的操作表示
这是一个很妙的 \(trick\),为什么?
初始 \(delta= \sum\limits_{i=1}^{k+1}a_i-\sum\limits_{i=n-k+1}^n=n\)
每次前缀 \(-1\) 一定会使 \(delta\) 减小(对于每个前缀 \(i\),都可以算出减小的大小 \(w_i\)
这相当于有 \(i\) 个物品,每个物品权值为 \(w_i\),无限背包,权值和 \(<n\) 的方案数
这最好的一点在于权值上限是 \(n\),可以暴力背包

时间复杂度 \(O(n^2)\)

#include <bits/stdc++.h>
#define F(i,x,y) for(int i=(x);i<=(y);i++)
#define DF(i,x,y) for(int i=(x);i>=(y);i--)
#define ms(x,y) memset(x,y,sizeof(x))
#define SZ(x) (int)x.size()-1
#define pb push_back
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
typedef pair<int,int> pii;
template<typename T> void chkmax(T &x,T y){ x=max(x,y);}
template<typename T> void chkmin(T &x,T y){ x=min(x,y);}
inline int read(){
    int FF=0,RR=1;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') RR=-1;
    for(;isdigit(ch);ch=getchar()) FF=(FF<<1)+(FF<<3)+ch-48;
    return FF*RR;
}
const int N=5010;
int n,Mod,f[N],w[N];
inline void inc(int &x,int y){ x+=y;if(x>=Mod) x-=Mod;}
int main(){
    n=read(),Mod=read();
    int k=(n-1)/2;// [1,k+1] and [n-k+1,n]
    F(i,1,n) w[i]=min(k+1,i)-max(0,i-(n-k+1)+1);
    f[0]=1;
    F(i,1,n) F(j,w[i],n) inc(f[j],f[j-w[i]]);
    int ans=0;
    F(i,0,n-1) inc(ans,f[i]);
    printf("%d\n",ans);
    return 0;
}

posted @ 2024-01-19 21:11  Farmer_D  阅读(14)  评论(0)    收藏  举报