Codeforces 383D. Antimatter

来源:互联网 发布:大学生防网络诈骗教育 编辑:程序博客网 时间:2024/06/05 16:12

     n个数(1..1000),从这串数中选取一个字串,任意添加数前的正负号,若以一种方案加上符号后该字串的和为0,则是一种可行的方案,问对这n个数共有多少种可行的方案(字串大小任意,至少为2(1个数怎么也凑不出0...))。n个数的和不超过10000.一般情况下,题目的条件都是有用的,这道题就是从n个数的和不超过10000入手.dp[i][j]记录以第i个数为终点,此时和为j的方案数.转移方程dp[i][j+a[i]]+=dp[i-1][j],dp[i][j-a[i]]-=dp[i-1][j]..边界dp[i][0]=1,因为空串不是符合要求的方案,所以在统计答案的时候要把每个dp[i][0]减掉1..n个数的和不超过10000,所以复杂度是1000*20000的,带着取模的操作,在cf上跑了100ms,只能说cf的服务里太强了...

#include <iostream>#include <cstdio>#include <algorithm>#include <cmath>#include <queue>#include <cstring>using namespace std;typedef long long ll;int dp[1010][20200];int n,m,p,q;int a[1010];int sum;const int mod=1000000007;int main(){//    freopen("in.txt","r",stdin);    scanf("%d",&n);    sum=0;    for (int i=1; i<=n; i++)    scanf("%d",&a[i]),sum+=a[i];    memset(dp,0,sizeof dp);    dp[0][0+sum]=1;    for (int i=1; i<=n; i++)    dp[i][0+sum]=1;    for (int i=1; i<=n; i++)    {     for (int j=-sum; j<=sum; j++)     if (dp[i-1][j+sum])     {         dp[i][j+sum+a[i]]+=dp[i-1][j+sum];         dp[i][j+sum+a[i]]%=mod;         dp[i][j+sum-a[i]]+=dp[i-1][j+sum];         dp[i][j+sum-a[i]]%=mod;     }//     for (int j=-sum; j<=sum; j++)//     cout<<dp[i][j+sum]<<" ";//     cout<<endl;    }     int ans=0;    for (int i=1; i<=n; i++)     ans+=dp[i][0+sum]-1,ans%=mod;    cout<<ans<<endl;    return 0;}


0 0
原创粉丝点击