LinghtOJ1132 Summing up Powers

来源:互联网 发布:淘宝新手入门教程视频 编辑:程序博客网 时间:2024/05/18 12:32

Given N and K, you have to find

(1K+2K+3K+...+NK)%232

Input
Input starts with an integer T (≤ 200), denoting the number of test cases.

Each case contains two integers N (1 ≤ N ≤ 1015) and K (0 ≤ K ≤ 50) in a single line.

Output
For each case, print the case number and the result.

Sample Input
3
3 1
4 2
3 3
Sample Output
Case 1: 6
Case 2: 30
Case 3: 36
题意就是求开始的那个式子。
不难看出递推式:
Fn=Fn1+nk
但是这样依旧没解决问题,我们要化出来的递推式中的元素应该要乘上1个相同的元素,然后才能构造成矩阵.也就是说比如x1a=x2,x2a=x3并且a为常数这种才可以。
所以如果nk 如果变成(n+1)k的话,需要加上C0kn0+C1kn1+C2kn2....+Ckknk也就是说我们需要n0,n1,n2...nk这些元素。
那么我们把上面的递推公式转化:
Fn+1=Fn+C0kn0+C1kn1+C2kn2+...+Ckknk
那么进行Fn+2的时候,上面n应该变成n+1。

(n+1)0=C00n0
(n+1)1=C01n0+C11n1
(n+1)2=C02n0+C12n1+C22n2

所以我们就可以构造矩阵:

[F11011121k]1C0kC1kC2kC3kCkk01000001100001210001331001C1kC2kC3kCkkn1

这样乘出来之后就可以得到Fn了。

#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>using namespace std;typedef unsigned int uint;typedef long long LL;//计算组合数uint c[52][52];void get_c(){    for(int i = 0; i <= 50; ++i)        for(int j = 0; j <= 50; ++j)    {        if(!j || i==j)c[i][j] = 1;        else c[i][j] = c[i-1][j]+c[i-1][j-1];    }}LL n;int k;int Size;struct matrix{    uint a[52][52]={{0}};    matrix operator * (const matrix b)const    {        matrix ans;        for(int i = 0; i < Size; ++i)            for(int k = 0; k < Size; ++k)if(a[i][k])                for(int j = 0; j < Size; ++j)                {                    ans.a[i][j] += a[i][k]*b.a[k][j];                }        return ans;    }};uint F(LL n){    matrix ans,base;    for(int j = 0; j <= k+1; ++j)ans.a[0][j] = 1;    base.a[0][0] = 1;    for(int i = 1; i <= k+1; ++i)base.a[i][0] = c[k][i-1];    for(int j = 1; j <= k+1; ++j)        for(int i = 1; i <= j; ++i)base.a[i][j] = c[j-1][i-1];        n--;        while(n)        {            if(n & 1LL)ans = ans*base;            base = base*base;            n >>= 1LL;        }        return ans.a[0][0];}int main(){    int t;    get_c();    scanf("%d",&t);    int ca = 0;    while(t--)    {        scanf("%lld%d",&n,&k);        Size = k+2;        printf("Case %d: %u\n",++ca,F(n));    }    return 0;}

232取模就是直接用unsig int就可以了。

原创粉丝点击