HLG 1396 射镖游戏【母函数】

题意: 

给你一个运动员的起始分数,分数为 N,你需要计算出有多少种投掷飞镖的方式能够把分数降到0. 不同的

方式意味着: 两两方式之间至少有一种方式的某个步骤和另一个不同,如果两个方式可以通过改变其中某种

方式相应步骤的顺序来使其和另一个方式相同的话,这两种方式算作一种。

分析:

比较明显的母函数,只不过有个地方需要注意,就是要开两个数组来维护总的情况数,即 先求出不包含X2 的情况的

组合数,然后用滚动数组c1 c2来存放至少含有一个X2的情况数,也就是 C数组里面存的都是符合条件的情况,

c[j+step]+={ c[j]       里面的每种情况都符合要求  

          { tmp[j]   里面的每种情况都不符合要求

code:

View Code
#include<stdio.h>
#include<string.h>
#define mod 2011
int main()
{
//    freopen("D:data.in","r",stdin);
    int c1[1111];
    int c2[1111];
    int tmp[1111];
    int g,a[100],i,j,k,n,top=0;
    for(i=1;i<=20;i++)
    {
        a[top++]=i;
        a[top++]=i*3;
    }
    a[top++]=25;
    a[top++]=50;
    g=top-1;
    for(i=1;i<=20;i++)
        a[top++]=i*2;
    for(i=0;i<=1001;i++)
    {
        tmp[i]=1;
        c2[i]=0;
    }
    for(i=1;i<g;i++)
    {
        for(j=0;j<=1001;j++)
            for(k=0;j+k<=1001;k+=a[i])
                c2[j+k]+=tmp[j]%mod;
        for(j=0;j<=1001;j++)
        {
            tmp[j]=c2[j]%mod;
            c2[j]=0;
        }
    }
    memset(c1,0,sizeof(c1));
    for(i=g;i<top;i++)
    {
        for(j=0;j<=1001;j++)
            for(k=a[i];j+k<=1001;k+=a[i])
                c2[j+k]+=tmp[j]%mod;
        for(j=0;j<=1001;j++)
            for(k=0;j+k<=1001;k+=a[i])
                c2[j+k]+=c1[j]%mod;
        for(j=0;j<=1001;j++)
        {
            c1[j]=c2[j]%mod;
            c2[j]=0;
        }
    }
    while(scanf("%d",&n),n)
        printf("%d\n",c1[n]);
    return 0;
}
posted @ 2012-05-17 21:34  'wind  阅读(284)  评论(0编辑  收藏  举报