[伯努利数] poj 1707 Sum of powers

本文提供了一种快速计算自然数幂次和的方法,利用伯努利数推导出多项式表达式,并通过代码实现最小公倍数计算。
部署运行你感兴趣的模型镜像

题目链接:

http://poj.org/problem?id=1707


Language:
Sum of powers
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 735 Accepted: 354

Description

A young schoolboy would like to calculate the sum 
 
for some fixed natural k and different natural n. He observed that calculating i k for all i (1<=i<=n) and summing up results is a too slow way to do it, because the number of required arithmetical operations increases as n increases. Fortunately, there is another method which takes only a constant number of operations regardless of n. It is possible to show that the sum S k(n) is equal to some polynomial of degree k+1 in the variable n with rational coefficients, i.e., 
 
We require that integer M be positive and as small as possible. Under this condition the entire set of such numbers (i.e. M, a k+1, a k, ... , a 1, a 0) will be unique for the given k. You have to write a program to find such set of coefficients to help the schoolboy make his calculations quicker.

Input

The input file contains a single integer k (1<=k<=20).

Output

Write integer numbers M, a k+1, a k, ... , a 1, a 0 to the output file in the given order. Numbers should be separated by one space. Remember that you should write the answer with the smallest positive M possible.

Sample Input

2

Sample Output

6 2 3 1 0

Source



题目意思:

已知并且求最小的M,使得a[k+1]---a[0]都为整数。

解题思路:
伯努利数:http://zh.wikipedia.org/wiki/%E4%BC%AF%E5%8A%AA%E5%88%A9%E6%95%B0


所以有1^k+2^k+3^k+...+n^k=1/(k+1)(C[k+1,0)*B[0]*n^(k+1-0)+C[k+1,1]*B[1]*n^(k+1-1)+...+C[k+1,j]*B[j]*n^(k+1-j)+...+C[k+1,k]*B[k]*n^(k+1-k))+n^k

先求出伯努利数,然后分母求最小公倍数即可。

注意n^k的系数要加上后面的n^k为C[k+1,1]*B[1]+(k+1)

最后只剩下分数加法了。注意最大公约数为负数的情况,强制转化为正数,用分子保存整个分数的正负性。

代码:

//#include<CSpreadSheet.h>

#include<iostream>
#include<cmath>
#include<cstdio>
#include<sstream>
#include<cstdlib>
#include<string>
#include<string.h>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#include<ctime>
#include<bitset>
#include<cmath>
#define eps 1e-6
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define ll __int64
#define LL long long
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#define M 1000000007
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

#define Maxn 25
ll C[Maxn][Maxn];
struct PP
{
    ll a,b;
}B[Maxn],ans[Maxn];

ll k;

ll gcd(ll a,ll b)
{
    if(a%b==0)
    {
        if(b>0)
            return b;
        return -b;
    }

    return gcd(b,a%b);
}

PP add(PP a,PP b) //模拟两个分数的加法
{
    if(!a.a) //如果有一个为0
        return b;
    if(!b.a)
        return a;

    ll temp=a.b/gcd(a.b,b.b)*b.b; //求出分母的最小公倍数
    //printf("%I64d\n",temp);
    PP res;
    res.a=temp/a.b*a.a+temp/b.b*b.a; //分子相加
    res.b=temp;

    if(res.a)  //约掉最大公约数
    {
        ll tt=gcd(res.a,res.b);
        res.b/=tt;
        res.a/=tt;
    }
    return res;

}

void init()
{
    memset(C,0,sizeof(C));

    for(int i=0;i<=25;i++)
    {
        C[i][0]=1;
        for(int j=1;j<i;j++)
            C[i][j]=C[i-1][j]+C[i-1][j-1];
        C[i][i]=1;
    }
    B[0].a=1,B[0].b=1;  //求伯努利数

    for(int i=1;i<=20;i++)  //用递推关系求
    {
        PP temp;
        temp.a=0;
        temp.b=0;

        for(int j=0;j<i;j++)
        {
            PP tt=B[j];

            tt.a=tt.a*C[i+1][j];
            //printf("::::%I64d %I64d:\n",tt.a,tt.b);
            if(tt.a)
            {
                ll te=gcd(tt.a,tt.b);
                tt.a/=te;
                tt.b/=te;
            }

            temp=add(temp,tt);

            //printf("i:%d j:%d %I64d %I64d:\n",i,j,temp.a,temp.b);
            //system("pause");
        }

        temp.a=-temp.a;
        temp.b*=C[i+1][i];
        //printf("%I64d %I64d\n",temp.a,temp.b);
        //system("pause");

        //printf("%I64d\n",gcd(temp.a,temp.b));
        if(temp.a)
        {
            ll te=gcd(temp.a,temp.b);
            temp.a/=te;
            temp.b/=te;
        }
        else
            temp.b=0;
        B[i]=temp;
        //printf("i:%d %I64d %I64d\n",i,B[i].a,B[i].b);
        //system("pause");
    }
}



int main()
{
   //freopen("in.txt","r",stdin);
   //freopen("out.txt","w",stdout);

   //printf("%I64d\n",gcd(-6,12));

   init();
   while(~scanf("%I64d",&k))
   {

       ll cur=1;

       for(int i=0;i<=k;i++)
       {
           if(i==1)
           {
               ans[i].a=k+1;  //B[1]=-1/2要加上后面多出来的n^k
               ans[i].b=2;
           }
           else
           {
               ans[i]=B[i];
               ans[i].a*=C[k+1][i];
           }

           if(ans[i].a) //约分
           {
               ll temp=gcd(ans[i].a,ans[i].b);
               ans[i].a/=temp;
               ans[i].b/=temp;
           }
           else
                ans[i].b=0;
           if(ans[i].b) //求分母的最小公倍数
                cur=cur/gcd(cur,ans[i].b)*ans[i].b;

       }
       printf("%I64d ",cur*(k+1));
       //printf("->%I64d %I64d %I64d\n",cur,ans[0].a,ans[0].b);
       for(int i=0;i<=k;i++) //求出通分后每一个系数
       {
           if(ans[i].b)
               ans[i].a=cur/ans[i].b*ans[i].a;
               //printf("i:%d %I64d\n",i,ans[i].a);
       }
       for(int i=0;i<=k;i++)
            printf("%I64d ",ans[i].a);
       printf("0\n"); //最后一个肯定是0
   }
   return 0;
}








您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

<think>好的,我现在需要处理用户关于伯努利学定义与计算方法的问题。首先,我得确认自己对这个概念的理解是否正确。伯努利是在学中用于论和分析中的特殊序列,我记得它们出现在泰勒展开式里,比如黎曼ζ函或者三角函的部分展开。但具体的定义可能需要进一步确认。用户可能希望得到明确的学定义和几种不同的计算方法。我需要先回忆伯努利的生成函,通常是用指生成函来定义的,可能是通过某个分式展开得到的。比如,生成函可能是t/(e^t-1),然后展开成幂级,系就是伯努利B_n。不过具体的公式可能需要查阅准确的定义,避免错误。 接下来是计算方法。常见的可能有递归公式、显式公式,或者与其他学对象的关系。比如递归公式的话,可能需要用到组合或者递推关系。另外,伯努利分为常规的和“第一伯努利”不同的定义,有时候B_1是-1/2,有时候可能不同,这需要注意区分。我还需要考虑用户是否需要具体的计算步骤或示例,比如用递归方法计算前几个伯努利。例如,B0=1,B1=-1/2,B2=1/6,B3=0,B4=-1/30等,这些初始值是否正确?可能需要验证。 另外,是否有其他的计算方法,比如通过黎曼ζ函的负奇值,或者欧拉-麦克劳林公式中的系?或者通过生成函的泰勒展开系直接计算?这些不同的方法可能需要分别解释,并指出它们的适用场景。 同时,用户可能对伯努利的应用感兴趣,但问题主要集中在定义和计算,所以应用部分可能不需要深入,但如果有相关的方法可以提及,比如在求和公式中的应用。 现在需要调用网络搜索工具来确认这些信息是否正确,补充可能遗漏的方法,并确保递归公式和其他公式的准确性。例如,递归公式是否正确,是否涉及到组合的求和,或者是否有显式的闭式表达式,如使用双曲函的展开式或者别的学工具。还需要注意格式要求,比如学公式必须用$或$$包裹,代码部分用三个反引号并指定语言类型。例如,如果给出计算伯努利的Python代码,需要用正确的语法格式,并且代码要准确有效。在整合信息时,要分步骤或方法,每个方法之间换行,避免使用第一人称和步骤性词汇。同时,确保引用来源的信息分散在回答中,而不是集中在末尾。最后,生成相关问题时要基于用户的原始问题和回答内容,比如可能涉及应用、与其他列的关系、历史背景等。需要至少三个相关问题,用字列表,并严格遵循格式要求。现在,我需要检查是否有遗漏的关键点,比如伯努利的递推公式是否准确,生成函的正确形式,以及不同的计算方法是否有明确的步骤。此外,确保回答中没有使用被禁止的词汇,结构清晰,符合用户的要求。</think>伯努利论和分析中的重要列,其学定义可通过生成函描述: $$ \frac{t}{e^t - 1} = \sum_{n=0}^{\infty} B_n \frac{t^n}{n!} $$ 其中 $B_n$ 表示第 $n$ 个伯努利,$B_0 = 1$,$B_1 = -\frac{1}{2}$,后续值交替出现零与非零项。 **计算方法** **递归公式** 通过组合递推计算: $$ \sum_{k=0}^n \binom{n+1}{k} B_k = 0 \quad (n \geq 1) $$ 例如计算 $B_2$: $$ \binom{3}{0}B_0 + \binom{3}{1}B_1 + \binom{3}{2}B_2 = 0 \Rightarrow 1 + 3(-\frac{1}{2}) + 3B_2 = 0 \Rightarrow B_2 = \frac{1}{6} $$ **显式公式** 利用双曲余切函展开: $$ \frac{t}{2} \coth\left( \frac{t}{2} \right) = \sum_{n=0}^\infty B_{2n} \frac{t^{2n}}{(2n)!} $$ 适用于计算偶伯努利,如 $B_4 = -\frac{1}{30}$。 **代码实现** ```python from sympy import bernoulli def calculate_bernoulli(n): return bernoulli(n) # 计算前6项 for i in range(6): print(f"B_{i} = {calculate_bernoulli(i)}") ``` 该代码使用符号计算库SymPy直接输出结果,避免手动递归计算误差。 **值特性** - 奇项 $B_{2n+1} = 0$($n \geq 1$) - 偶项符号交替变化 - 与黎曼ζ函关系:$ \zeta(-n) = -\frac{B_{n+1}}{n+1} \quad (n \geq 1) $
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值