1 条题解

  • 0
    @ 2026-8-31 0:51:17

    过了所有大样例和洛谷数据。虽然 4h 才切,但也算是一雪前耻了。

    :::info[Hint]{open} 正难则反,取不到最大原价总和只有两种情况:

    • 最优解选性价比较低的 22,小 R 选性价比较高的 11,且 11 的原价低于 22 的原价。

    • 最优解选性价比中的 22,小 R 选性价比较高的 11 和性价比较低的 11,且两个 11 的原价之和低于 22 的原价。

    上述的 22 是最优解中选取的性价比最低的 22,上述的 11 是小 R 选取的性价比最低的 11

    性价比高于所选性价比最低的 2222 都必选,性价比高于所选性价比最低的 1111 都必选。 :::

    :::info[Tip] 一个组合意义显然成立的恒等式:

    $$\sum_{i=0}^{k}\dbinom{n}{i}\dbinom{m}{k-i}=\dbinom{n+m}{k}$$

    :::

    按原价从大到小排序,枚举:(记 cc1i11\sim i-122 的数量)

    • 对于第一种情况,枚举最优解的 22(记为 ii)以及小 R 的 11(记为 jj),则 ai>aj>12aia_i>a_j>\frac{1}{2}a_i,则方案数为:
    $$\sum_{c=0}^{i-1}\dbinom{i-1}{c}\dbinom{j-i-1}{m-(i-1+c)-2}=\dbinom{j-2}{m-i-1}$$

    :::info[分析] 最优解选了 1i11\sim i-1 中的所有、iii+1j1i+1\sim j-1 中的 11

    小 R 选了 1i11\sim i-1 中的所有、i+1j1i+1\sim j-1 中的 11jj。 :::

    • 对于第二种情况,枚举最优解的 22(记为 ii)以及小 R 的性价比较高的 11(记为 jj),则 ai>aj>12aia_i>a_j>\frac{1}{2}a_i,设 pp 为使得 ak+aj<aia_k+a_{j}< a_{i}(即可以成为性价比较低的 11)的最小的 kk,则方案数为:
    $$\sum_{k=p}^{n}2^{n-k}\cdot\sum_{c=0}^{i-1}\dbinom{i-1}{c}\dbinom{j-i-1}{m-(i-1+c)-2}=(2^{n-p+1}-1)\cdot\dbinom{j-2}{m-i-1}$$

    :::info[分析] 最优解选了 1i11\sim i-1 中的所有、iii+1j1i+1\sim j-1 中的 11

    小 R 选了 1i11\sim i-1 中的所有、i+1j1i+1\sim j-1 中的 11jjkk。 :::

    于是在 i,ji,j 一定时,二种情况的方案数之和就是:

    2np+1(j2mi1)2^{n-p+1}\cdot\dbinom{j-2}{m-i-1}

    pp 使用双指针维护即可。

    时间复杂度 O(n2)\mathcal{O}(\sum n^2),空间复杂度 O(n2)\mathcal{O}(n^2)O(n)\mathcal{O}(n)

    :::success[[NOIP2025] 清仓甩卖 - sale.cpp]

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=5010;
    const int mod=998244353;
    int dp[maxn][maxn],pre[maxn],a[maxn];
    int main(){
        ios::sync_with_stdio(0);
        cin.tie(0); cout.tie(0);
        dp[0][0]=pre[0]=1;
        for(int i=1;i<=maxn-10;i++){
            dp[i][0]=1;
            pre[i]=pre[i-1]<<1;
            if(pre[i]>=mod) pre[i]-=mod;
            for(int j=1;j<=i;j++){
                dp[i][j]=dp[i-1][j]+dp[i-1][j-1];
                if(dp[i][j]>=mod) dp[i][j]-=mod;
            }
        }
        int c,t;cin>>c>>t;
        while(t--){
            int n,m;cin>>n>>m;
            for(int i=1;i<=n;i++) cin>>a[i];
            sort(a+1,a+1+n,greater<int>());
            long long ans=0;
            for(int i=1;i<=n;i++){
                if(m-i-1<0) break;
                int p=n+1;
                for(int j=max(i+1,m-i+1);j<=n;j++){
                    if(a[i]==a[j]) continue;
                    if(a[i]>=(a[j]<<1)) break;
                    while(p>1 and a[p-1]+a[j]<a[i]) p--;
                    ans+=1ll*dp[j-2][m-i-1]*pre[n-p+1]%mod;
                }
            }
            cout<<(pre[n]-ans%mod+mod)%mod<<"\n";
        }
        return 0;
    }
    

    :::

    • 1

    信息

    ID
    1921
    时间
    1000ms
    内存
    512MiB
    难度
    10
    标签
    递交数
    14
    已通过
    1
    上传者