1 条题解

  • 0
    @ 2026-8-29 0:52:53

    对于任意一个 nn 边形,要满足所有小木棍的长度之和大于所有小木棍的长度最大值的两倍,也就是 i=1n1ai>an\sum_{i=1}^{n-1}a_i>a_n,其中 aa 数组从小到大排序。

    kik_i 表示在用最小的 ii 根木棍中,必须使用第 ii 根木棍,拼成多变形的数量。

    所以答案就是 i=1nki\sum_{i=1}^n k_i

    kik_i 就是在前 i1i-1 根木棍中,选取任意根木棍,始其总和大于 aia_i(赛时把大于打成大于等于,调了好久)。 Tips: 只选取两根木棍时,因为 aa 是从小到大排列的,因此前面的一项肯定不能大于后面一项。

    你会发现这个东西很眼熟,就像是背包。

    所以我们可以列出 DP 式,设 dpi,jdp_{i,j} 表示选取前 ii 根木棍中,任意的选取木棍,始总和大于 jj 的方案数。 所以 DP 式的转移是 dpi,j=dpi1,jai+dpi1,j+[ai>j]dp_{i,j}=dp_{i-1,j-a_i}+dp_{i-1,j}+[a_i>j],其中 dpi1,jaidp_{i-1,j-a_i} 是选择了第 ii 根木棍的情况,dpi1,jdp_{i-1,j} 是不选择了第 ii 根木棍的情况,[ai>j][a_i>j] 表示就只选第 ii 根木棍的情况。

    答案就是 i=1ndpi1,ai\sum_{i=1}^ndp_{i-1,a_i}取模啥的请自行添加!

    Code:

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    int a[10010],dp[5010][5010];
    int main()
    {
    //  freopen("polygon.in","r",stdin);
    //  freopen("polygon.out","w",stdout);
    	int n;
    	ll ans=0;
    	cin>>n;
    	for(int i=1;i<=n;i++)cin>>a[i];
    	sort(a+1,a+n+1);
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=0;j<=5000;j++)
    		{
    			dp[i][j]=((a[i]>j)+dp[i-1][max(j-a[i],0)]+dp[i-1][j])%998244353;
    		}
    	}
    	for(int i=1;i<=n;i++)ans=(ans+dp[i-1][a[i]])%998244353;
    	cout<<ans;
    	return 0;
    }
    
    • 1

    信息

    ID
    1355
    时间
    1000ms
    内存
    512MiB
    难度
    8
    标签
    递交数
    191
    已通过
    31
    上传者