1. 程式人生 > >Luogu P1566 【加等式】

Luogu P1566 【加等式】

ring HR family clu sizeof namespace font ret using

看到這道題,我們首先註意到“找出其所有的加等式的個數”,自然地考慮運用計數DP求出若幹數相加的和的個數

考慮將每個元素排序後DP處理若幹數相加的和的個數

用f[i]表示

對於一個數a[i],對於前i-1個元素選或不選的和j-a[i],選a[i]後的和為j,則組成j-a[i]的方案數會對組成j的方案數做出大小為f[j-a[i]]的貢獻,

所以枚舉i,j,像這樣轉移f[j]+=f[j-a[i]]

考慮加等式的統計:

對於一個整數集合,我們定義“加等式”如下:集合中的某一個元素可以表示成集合內其他元素之和。

對於一個數,我們已經得到它之前所有數選或不選的和等於它的方案數,為了避免漏記,考慮到對於i>j,i一定不會作為j的加等式中的元素出現,所以我們可以在輸入時排序,從小到大DP,對於每個元素a[i],統計它對答案f[a[i]]的貢獻



上代碼:

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int t,m,a[40],f[30010],sum;
int main()
{
    cin>>t;
    while(t--)
    {
        cin>>m;
        sum=0;
        for(int i=1;i<=m;i++)
        {
            cin>>a[i];
            sum
+=a[i]; } sort(a+1,a+m+1); memset(f,0,sizeof(f)); f[0]=1; int ans=0; for(int i=1;i<=m;i++) { ans+=f[a[i]]; for(int j=sum;j>=a[i];j--) f[j]+=f[j-a[i]]; } cout<<ans<<endl; }
return 0; }

Luogu P1566 【加等式】