HDU 4927 大数

题意非常easy:

对于长度为n的数。做n-1遍。生成的新数列:

b1=a2-a1   b2=a3-a2  b3=a4-a3

c1=b2-b1   c2=b3-b2

ans=c2-c1

最后推出公式:  为n所在行的杨辉三角

对于例子:

3

1 2 3

ans=1*1-2*2+1*3=0

4

1 5 7 2

ans=-1*1+3*5-3*7+1*2=-5

求杨辉三角每一个数的时候能够优化一下,后一个数由前一个各乘除一次就好了

JAVA用大数秒A。

BUT 不会JAVA  - -#

蛋疼用C++模拟大数。。

#include "stdio.h"
#include "string.h"
int a[3010];
__int64 mark[3010],ans[3010],c[3010];
int Max(int a,int b)
{
    if (a<b) return b;else return a;
}

void make_mul(int x)
{
    int i;
    for (i=1;i<=mark[0];i++)
        mark[i]*=x;

    for (i=1;i<=mark[0];i++)
    {
        mark[i+1]+=mark[i]/1000000;
        mark[i]%=1000000;
    }
    while (mark[mark[0]+1]!=0)
    {
        mark[0]++;
        mark[mark[0]+1]=mark[mark[0]]/1000000;
        mark[mark[0]]%=1000000;
    }

}

void make_div(int x)
{
    int i;
    for (i=mark[0];i>=2;i--)
    {
        mark[i-1]+=(mark[i]%x)*1000000;
        mark[i]/=x;
    }
    mark[1]/=x;
    while (mark[mark[0]]==0) mark[0]--;
}

void make_add()
{
    int i,op;
    if (ans[0]>0)
    {
        for (i=1;i<=mark[0];i++)
        {
            ans[i]+=mark[i];
            ans[i+1]+=ans[i]/1000000;
            ans[i]%=1000000;
        }
        while (ans[ans[0]+1]!=0)
        {
            ans[0]++;
            ans[ans[0]+1]=ans[ans[0]]/1000000;
            ans[ans[0]]%=1000000;
        }
        return ;
    }
    else
    {
        if (-ans[0]>mark[0]) op=-1;
        else if (-ans[0]<mark[0]) op=1;
        else
        {
            for (i=mark[0];i>=1;i--)
            if (mark[i]>ans[i]) { op=1;break;}
            else if (mark[i]<ans[i]) { op=-1; break;}

            if (i==0)
            {
                memset(ans,0,sizeof(ans));
                ans[0]=1;
                return ;
            }
        }

            if (op==1)
            {
                for (i=1;i<=mark[0];i++)
                {
                    ans[i]=mark[i]-ans[i];
                    if (ans[i]<0)
                    {
                        mark[i+1]--;
                        ans[i]+=1000000;
                    }
                }
                ans[0]=-ans[0];
                while (ans[ans[0]]==0) ans[0]--;
            }
            else
            {
                for (i=1;i<=-ans[0];i++)
                {
                    ans[i]=ans[i]-mark[i];
                    if (ans[i]<0)
                    {
                        ans[i+1]--;
                        ans[i]+=1000000;
                    }
                }
                while (ans[-ans[0]]==0) ans[0]++;
            }

    }
}

void make_red()
{
    int i,op;
    if (ans[0]<0)
    {
        for (i=1;i<=mark[0];i++)
        {
            ans[i]+=mark[i];
            ans[i+1]+=ans[i]/1000000;
            ans[i]%=1000000;
        }
        while (ans[-ans[0]+1]!=0)
        {
            ans[0]--;
            ans[-ans[0]+1]=ans[-ans[0]]/1000000;
            ans[-ans[0]]%=1000000;
        }
        return ;
    }
    else
    {
        if (ans[0]>mark[0]) op=1;
        else if (ans[0]<mark[0]) op=-1;
        else
        {
            for (i=mark[0];i>=1;i--)
            if (mark[i]>ans[i]) { op=-1;break;}
            else if (mark[i]<ans[i]) { op=1; break;}

            if (i==0)
            {
                memset(ans,0,sizeof(ans));
                ans[0]=1;
                return ;
            }
        }

            if (op==1)
            {
                for (i=1;i<=mark[0];i++)
                {
                    ans[i]=ans[i]-mark[i];
                    if (ans[i]<0)
                    {
                        ans[i+1]--;
                        ans[i]+=1000000;
                    }
                }
                while (ans[ans[0]]==0) ans[0]--;
            }
            else
            {
                for (i=1;i<=mark[0];i++)
                {
                    ans[i]=mark[i]-ans[i];
                    if (ans[i]<0)
                    {
                        mark[i+1]--;
                        ans[i]+=1000000;
                    }
                }
                ans[0]=mark[0];
                while (ans[ans[0]]==0) ans[0]--;
                ans[0]=-ans[0];
            }

    }

}
int main()
{
    int t,n,i,x,y,j,m,op;
    scanf("%d",&t);
    while (t--)
    {
        scanf("%d",&n);
        for (i=1;i<=n;i++)
            scanf("%d",&a[i]);

        memset(ans,0,sizeof(ans));
        ans[0]=1;
        if (i==1)
        {
            printf("%d\n",a[1]);
            continue;
        }
        memset(mark,0,sizeof(mark));
        mark[0]=1;
        mark[1]=1;
        if (n%2==1) ans[1]=a[1];
        else ans[1]=-a[1];
        x=1;
        y=n-1;
        for (i=2;i<=n;i++)
        {
            make_mul(y);
            y--;
            make_div(x);
            x++;
            memcpy(c,mark,sizeof(mark));

            make_mul(a[i]);
            if (n%2==1)
            {
                if (i%2==1) make_add();
                else make_red();
            }
            else
            {
                if (i%2==0) make_add();
                else make_red();
            }
            memcpy(mark,c,sizeof(c));

        }

        if (ans[0]>0)
        {
            printf("%I64d",ans[ans[0]]);
            for (i=ans[0]-1;i>=1;i--)
                printf("%06I64d",ans[i]);
            printf("\n");
        }
        else
        {
            printf("-");
            printf("%I64d",ans[-ans[0]]);
            for (i=-ans[0]-1;i>=1;i--)
                printf("%06I64d",ans[i]);
            printf("\n");
        }

    }
    return 0;
}
时间: 2024-10-14 01:29:59

HDU 4927 大数的相关文章

HDU 4927 大数运算

模板很重要 #include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; #define MAXN 9999 #define MAXSIZE 10 #define DLEN 4 class BigInt { private: int a[500]; //可以控制大数的位数 i

HDU 4927 Series 1(推理+大数)

HDU 4927 Series 1 题目链接 题意:给定一个序列,要求不断求差值序列,直到剩一个,输出这个数字 思路:由于有高精度一步,所以要推理一下公式,其实纸上模拟一下很容易推出公式就是一个类似杨辉三角的组合数求和,不过奇数位置是加,偶数位置是减,然后高精度过掉 代码: 本人的第一个JAVA程序^ ^ import java.util.Scanner; import java.math.BigInteger; public class Main { public static void ma

多校第六场 HDU 4927 JAVA大数类

题目大意:给定一个长度为n的序列a,每次生成一个新的序列,长度为n-1,新序列b中bi=ai+1?ai,直到序列长度为1.输出最后的数. 思路:这题实在是太晕了,比赛的时候搞了四个小时,从T到WA,唉--对算组合还是不太了解啊,现在对组合算比较什么了-- import java.io.*; import java.math.*; import java.util.*; public class Main { public static void main(String[] args) { Sca

HDU 4927 Series 1 java大数

java mle前会wa 或者 t 这种事我会乱说? import java.math.*; import java.util.*; import java.io.*; public class Main { BigInteger[] a = new BigInteger[3007]; public void work() { int T; T = cin.nextInt(); while (T-- > 0) { int n; n = cin.nextInt(); for (int i = 0;

hdu 4927 java求组合数(大数)

import java.util.Scanner; import java.math.BigInteger; public class Main { private static int [] a = new int[3005]; private static int T; private static int n; public static void solve() { BigInteger rs = BigInteger.ZERO; BigInteger temp = BigInteger

hdu 4927 Series 1(组合,java大数)

http://acm.hdu.edu.cn/showproblem.php?pid=4927 比赛时分分钟推出来公式后,陷入无限的tle中.起初想处理一遍,但是3000的数量内存装不下,直接编译就不过.为了不超内存,然后又试着把三个数合并为一个,四个数合并一个,100个数合并为一个,还是TLE.. 说到底还是数学不好啊,杨辉三角的第n行的第m个数为组合数c[n-1][m-1]. 应用c[n][m] = c[n][m-1]*(n-m+1)/m,就可以快速递推出第n行的数,这样就能省去预处理的时间以

hdu 4927 Java大数

http://acm.hdu.edu.cn/showproblem.php?pid=4927 [解法]:最后的结果是C(n-1,0)*a[n] -C(n-1, 1) * a[n-1] ……C(n-1,n-1)*a[1].符号位一正一负交替. 因为n有3000 之大,算C(n,i) 时要用到大数. 诶  其实早就把公式推出来了,就是坑在Java语言不熟悉,在编译的时候总是出现这个 我们一直以为是语法错误,但是又发现有什么地方写错了,卡了几个小时,人都要抓狂了. 今天拿着后面过的代码跟第一个交的比较

hdu 4927 Series 1

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4927 题目大意:就是把相邻的两个数想减,然后会得到一串数,然后继续想减,当还剩一个数时,问这个数是多少. 思路:开始解题时,直接模拟,结果果断WA,然后就在那儿找规律,找出来后发现是各个数的绝对值是杨辉三角(因为这个杨辉三角是正负交替出现的),有啦规律,然后就开始做题,结果还是错啦几次,然后发现是大数问题.然后又改代码,因为数组开的太大,java没过,因为当时用打表求得杨辉三角,所以一直WA,后来才

HDU 4927 Series 1(高精度+杨辉三角)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4927 解题报告:对于n,结果如下: C(0,n-1) *A[n] - C(1,n-1) * A[n-1] + C(2,n-1) * A[n-2] - C(3,n-1) * A[n-3] ....... C(n-1,n-1) * A[1]; n <= 3000,到了后面二项式会很大,因为要用到高精度的乘法和除法,所以直接用java的大数类写了,简单多了. 1 import java.math.BigI