uva 766 - Sum of powers(数学+递推)

题目连接:uva 766 - Sum of powers

题目大意:将Sk(n)=∑i=1nik化简成Sk(n)=ak+1nk+1+aknk+?+a0M

解题思路:

已知幂k,并且有(n+1)k=C(kk)nk+C(k?1k)nk?1+?+C(0k)n0结论。

所以令 (n+1)k+1?nk+1=C(kk+1)nk+C(k?1k+1)nk?1+?+C(0k+1)n0

nk+1?(n?1)k+1=C(kk+1)(n?1)k+C(k?1k+1)(n?1)k?1+?+C(0k+1)(n?1)0

2k+1?1k+1=C(kk+1)1k+C(k?1k+1)1k?1+?+C(0k+1)10

将各项累加起来的(n+1)k?1=C(kk+1)Sk(n)+C(k?1k+1)Sk?1(n)+?+C(0k+1)S0(n)

#include <cstdio>
#include <cstring>

typedef long long ll;
const int N = 25;

ll m[N], a[N][N];
ll C[N][N];

ll gcd (ll a, ll b) {
    return b == 0 ? a : gcd(b, a%b);
}

inline ll cal (ll d) {
    if (d < 0)
        return -d;
    return d;
}

inline ll sign (ll d) {
    if (d > 0)
        return 1;
    else if (d < 0)
        return -1;
    else
        return 0;
}

void del (ll& t, ll* p, int n) {
    ll d = gcd(t, p[0]);
    for (int i = 1; i <= n; i++) {
        if (p[i] == 0)
            continue;
        d = gcd(d, cal(p[i]));
    }

    t /= d;
    for (int i = 0; i <= n; i++)
        p[i] = cal(p[i]) / d * sign(p[i]);
}

void add (ll* p, ll* q, ll k, ll& t, ll f, int n) {

    for (int i = 0; i <= n; i++)
        p[i] = p[i] * f - q[i] * k * t;
    t *= f;

    del(t, p, n);
}

void init () {
    C[0][0] = 1;
    for (int i = 1; i < N; i++) {
        C[0][i] = C[i][i] = 1;
        for (int j = 1; j < i; j++)
            C[j][i] = C[j-1][i-1] + C[j][i-1];
    }

    memset(a, 0, sizeof(a));
    m[0] = 1;
    a[0][1] = 1;

    for (int i = 1; i <= 20; i++) {

        int u = i+1;
        for (int j = 1; j <= u; j++)
            a[i][j] += C[j][u];

        m[i] = 1;
        for (int j = 0; j < i; j++) {
            add (a[i], a[j], C[j][u], m[i], m[j], u);

            /*
            for (int x = 0; x <= j + 1; x++) {
                a[i][x] -= (a[j][x] * C[j][u] * tmp / m[j]);
            }
            */
        }

        m[i] *= C[i][u];
        del(m[i], a[i], u);
    }
}

int main () {
    init();
    int cas, k;
    scanf("%d", &cas);

    while (cas--) {
        scanf("%d", &k);
        printf("%lld", m[k]);
        for (int i = k+1; i >= 0; i--)
            printf(" %lld", a[k][i]);
        printf("\n");
        if (cas)
            printf("\n");
    }
    return 0;
}

uva 766 - Sum of powers(数学+递推)

时间: 2024-08-07 17:02:14

uva 766 - Sum of powers(数学+递推)的相关文章

UVA 766 - Sum of powers(伯努利数)

766 - Sum of powers 题意:求    转化成 的各系数 思路:在wiki看了伯努利数的性质,  可以推成 . 然后B为伯努利数,有公式, 如此一来就可以去递推求出每项伯努利数了,然后在根据n去通分,求出每一项的答案,中间过程用到了分数的运算. 代码: #include <stdio.h> #include <string.h> long long gcd(long long a, long long b) { if (!b) return a; return gc

uva live 4123 Glenbow Museum 数学递推

// uva live 4123 Glenbow Museum 数学递推 // // 题目大意: // // 对于一个边平行于坐标轴的多边形,我们可以用一个序列来描述,R和O,R表示 // 该顶点的角度为90度,O表示该定点的角度为270.给定序列的长度.问能由这些RO序 // 列组成的星型多边形(内部存在一个点可以看到所有的节点的多边形)的方法数有多少. // // 解题思路: // // 顶点数一定是序列的长度.n小于4无法组成多边形.n为奇数的时候也不行.设R的个数有 // x个,O的个数

UVA - 12295 Optimal Symmetric Paths (递推)

Description  Optimal Symmetric Paths  You have a grid of n rows and n columns. Each of the unit squares contains a non-zero digit. You walk from the top-left square to the bottom-right square. Each step, you can move left, right, up or down to the ad

UVA - 590Always on the run(递推)

题目:UVA - 590Always on the run(递推) 题目大意:有一个小偷现在在计划着逃跑的路线,但是又想省机票费.他刚开始在城市1,必须K天都在这N个城市里跑来跑去,最后一天达到城市N,问怎样计划路线的得到最少的费用. 解题思路:一开始题目意思就理解有些问题. dp[k][i]:代表在第k天小偷从某一个城市(除了i)坐飞机飞到城市i(到达城市i也是在这一天).第k天的话,就看这一天坐哪个航班,加上之前的费用是最小的,就选这个方案.然后k+ 1天就又是由第k天推出来的. 状态转移方

UVA - 348Optimal Array Multiplication Sequence(递推)

题目:Optimal Array Multiplication Sequence 题目大意:给出N个矩阵相乘,求这些矩阵相乘乘法次数最少的顺序. 解题思路:矩阵相乘不满足交换率但满足结合率.dp[i][j] 代表第1个矩阵到第j个矩阵之间的最少的乘法次数,转移状态方程:dp[i][j] = Min(dp[i][k] + dp[k + 1][j]  + A[i - 1] * A[k] *A[j]) k>= i && k <= j - 1.A0A1A2A3..Ak  |  Ak+1

HDU2047 阿牛的EOF牛肉串 【数学递推】

阿牛的EOF牛肉串 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 19521    Accepted Submission(s): 9125 Problem Description 今年的ACM暑期集训队一共有18人,分为6支队伍.其中有一个叫做EOF的队伍,由04级的阿牛.XC以及05级的COY组成.在共同的集训生活中,大家建立了深

UVA 11427 - Expect the Expected(概率递推期望)

UVA 11427 - Expect the Expected 题目链接 题意:玩一个游戏,赢的概率p,一个晚上能玩n盘,如果n盘都没赢到总赢的盘数比例大于等于p,以后都不再玩了,如果有到p就结束 思路:递推,dp[i][j]表示玩i盘,赢j盘的概率,那么一个晚上玩了n盘小于p的概率递推式为: dp(i,j)=dp(i?1,j)?(1?p)+dp(i?1,j?1)?p 总和为Q=dp(n,0)+dp(n,1)+...+dp(n,x)(x/n<p) 那么每个晚上失败的概率Q就求出来了,那么平均玩的

UVa 10943 (数学 递推) How do you add?

将K个不超过N的非负整数加起来,使它们的和为N,一共有多少种方法. 设d(i, j)表示j个不超过i的非负整数之和为i的方法数. d(i, j) = sum{ d(k, j-1) | 0 ≤ k ≤ i },可以理解为前j-1个数之和为i-k,最后一个数为k 还有一种更快的递推办法,把这个问题转化为将N个小球放到K个盒子中的方法数,盒子可以为空. 就等价于求x1 + x2 +...+ xK = N的非负整数解的个数,根据组合数学的知识容易算出结果为C(N+K-1, K-1). 所以也可以这样递推

UVa 825【简单dp,递推】

UVa 825 题意:给定一个网格图(街道图),其中有一些交叉路口点不能走.问从西北角走到东南角最短走法有多少种.(好像没看到给数据范围...) 简单的递推吧,当然也就是最简单的动归了.显然最短路长度就是row+col.求种数就从开始往后推. 由于第一行第一列也有可能是障碍点,所以初始化时要注意这一点,或者干脆就只初始化f[0][1]=1.i.j都从1开始递推到更方便.还有题目输入输出比较坑.输入我用的是sstream和stream,方便很多,要不还要按照字符串输入再手动转化成数字.输出让每组隔