USACO 2009 Mar CowFrisbeeTeam

来源:互联网 发布:linux shell脚本教程 编辑:程序博客网 时间:2024/05/17 23:37
既然是求和为F的倍数的方案数,我们定义dp[i][j]为第j 头牛时和为i 的方案数,这是很基础的,我们又很容易得到若使i 模上F,答案并不会有区别,我们就将所有数模上F,同时得到的和也模上F,那么最多就只有1000种和的可能性[0,F-1].

然后就是很平常的DP了.(这么简单的题目连Chongkan也写得出来吧……)

#include<cstdio>#include<cstring>#define M 2005#define P 100000000int dp[1001][M],Po[M];void Add(int &x,int y){    x+=y;    if(x>=P)x-=P;}int main(){    int n,f;    scanf("%d %d",&n,&f);    for(int i=1;i<=n;i++)scanf("%d",&Po[i]);    dp[Po[1]%f][1]=1;    for(int i=1;i<n;i++){        Add(dp[Po[i+1]%f][i+1],1);        for(int j=0;j<f;j++)            Add(dp[j][i+1],dp[j][i]),Add(dp[(j+Po[i+1])%f][i+1],dp[j][i]);    }    printf("%d\n",dp[0][n]);    return 0;}


然而可以省下一维,为避免重复计算,采用一个临时数组暂存一下。

#include<stdio.h>#define P 100000000#define M 1005int A[M<<1],dp[M],T[M];int main(){    int n,f;    scanf("%d %d",&n,&f);    for(int i=1;i<=n;i++)        scanf("%d",&A[i]);    dp[A[1]%f]=1;    for(int i=2;i<=n;i++){        for(int j=0;j<f;j++)            T[(j+A[i])%f]=dp[j];        T[A[i]%f]++;//直接取        for(int j=0;j<f;j++)            dp[j]=(T[j]+dp[j])%P;        }    printf("%d\n",dp[0]);    return 0;}



0 0