URAL 1036

题目大意:求前N位与后N位各个位和相等且总和等于S的2N位数的个数。

Time Limit:2000MS     Memory Limit:16384KB     64bit IO Format:%I64d & %I64u

数据规模:1<=N<=50,0<=S<=1000。

理论基础:无。

题目分析:用dp[i][j]表示前i位和为j的数的个数,那么答案就是:dp[N][S/2]*dp[N][S/2]。一定要注意,当S为奇数时无解的单独处理。

状态转移方程:dp[i][j]=sum(dp[i-1][j-k],0<=k<=9)。可想而知最后的数一定会很大。所以注意精度问题。

代码如下:

 

#include<iostream>

#include<cstring>

#include<string>

#include<cstdlib>

#include<cstdio>

#include<cmath>

#include<algorithm>

#include<queue>

#include<ctime>

#include<vector>

using namespace std;

typedef double db;

#define DBG 1

#define maa (1<<31)

#define mii ((1<<31)-1)

#define ast(b) if(DBG && !(b)) { printf("%d!!|\n", __LINE__); while(1) getchar(); }  //调试

#define dout DBG && cout << __LINE__ << ">>| "

#define pr(x) #x"=" << (x) << " | "

#define mk(x) DBG && cout << __LINE__ << "**| "#x << endl

#define pra(arr, a, b)  if(DBG) {\

    dout<<#arr"[] |" <<endl; \

    for(int i=a,i_b=b;i<=i_b;i++) cout<<"["<<i<<"]="<<arr[i]<<" |"<<((i-(a)+1)%8?" ":"\n"); \

    if((b-a+1)%8) puts("");\

}

template<class T> inline bool updateMin(T& a, T b) { return a>b? a=b, true: false; }

template<class T> inline bool updateMax(T& a, T b) { return a<b? a=b, true: false; }

typedef long long LL;

typedef long unsigned int LU;

typedef long long unsigned int LLU;

#define N 100

#define M 50

#define S 1000

typedef struct bign

{

    int digit[N+1];

    int lenth;

    void valid()

    {

        int i=0,n=lenth-1;

        while(i<n)

        {

            if(digit[i]>=1000)

            {

                digit[i+1]=digit[i]/1000+digit[i+1];

                digit[i]=digit[i]%1000;

            }

            i++;

        }

        while(digit[i])

        {

            if(digit[i]>=1000)

            {

                digit[i+1]=digit[i]/1000;

                digit[i]=digit[i]%1000;

                lenth++;

            }

            i++;

        }

    }

    bign(){memset(digit,0,sizeof(digit));lenth=1;}

    bign operator * (const bign& b)const

    {

        bign c;

        for(int i=0;i<lenth;i++)

        {

            for(int j=0;j<lenth;j++)

            {

                c.digit[i+j]=c.digit[i+j]+digit[i]*b.digit[j];

            }

        }

        c.lenth=lenth+b.lenth-1;

        c.valid();

        return c;

    }

    bign operator + (const bign& b)const

    {

        bign c;

        c.lenth=max(b.lenth,lenth);

        for(int i=0;i<c.lenth;i++)

        {

            c.digit[i]=digit[i]+b.digit[i];

        }

        c.valid();

        return c;

    }

    bign operator = (bign a)

    {

        lenth=a.lenth;

        for(int i=0;i<a.lenth;i++)

        {

            digit[i]=a.digit[i];

        }

        return *this;

    }

    bign operator = (int a)

    {

        digit[0]=a;

        valid();

        return *this;

    }

}Ans;

Ans dp[M+1][S+1],ans;

int n,s;

int main()

{

    scanf("%d%d",&n,&s);

    if(s&1)

    {

        printf("0\n");

        exit(0);

    }

    s/=2;

    for(int i=0;i<=9;i++)dp[1][i]=1;

    for(int i=2;i<=n;i++)

    {

        for(int j=0;j<=s;j++)

        {

            for(int k=0;k<=9&&k<=j;k++)

            {

                dp[i][j]=dp[i][j]+dp[i-1][j-k];

            }

        }

    }

    ans=dp[n][s]*dp[n][s];

    printf("%d",ans.digit[ans.lenth-1]);

    for(int i=ans.lenth-2;i>=0;i--)

    {

        printf("%03d",ans.digit[i]);

    }

    puts("");

	return 0;

}
其中,对于高精度的运算只涉及到赋值与乘法,加法运算,自己编写代码也不是很难。

 

 

你可能感兴趣的:(r)