srm#397_div1_500pt 矩阵乘法+快速模幂

题目地址:srm#397_div1_500

题目描述:

Problem Statement

 

NOTE: This problem statement contains superscripts that may not display properly if viewed outside of the applet.


You are given ints n and k. Return the value of the sum 1k + 2k + 3k + ... + nk modulo 1000000007.

Definition

 
Class:SumOfPowers
Method:value
Parameters:int, int
Returns:int
Method signature:int value(int n, int k)
(be sure your method is public)

Limits

 
Time limit (s):2.000
Memory limit (MB):64

Constraints

-n will be between 1 and 109, inclusive.
-k will be between 1 and 50, inclusive.

Examples

0) 
 
5
1
Returns: 15
Here, we have arithmethic progression: 1 + 2 + 3 + 4 + 5 = 15.
1) 
 
4
2
Returns: 30
Just a little bit more complicated example here: 12 + 22 + 32 + 42 = 1 + 4 + 9 + 16 = 30.
2) 
 
13
5
Returns: 1002001
This one would be harder to check by hand.
3) 
 
123456789
1
Returns: 383478132

This problem statement is the exclusive and proprietary property of TopCoder, Inc. Any unauthorized use or reproduction of this information without the prior written consent of TopCoder, Inc. is strictly prohibited. (c)2003, TopCoder, Inc. All rights reserved.     


构造一个k+2阶矩阵;

这里n比较大 显然我们接受不了O(n)的复杂度

最好的方法就是像求Fibonacci数列第n项一样用矩阵乘法+快速幂做


要实现求和长度在k左右的递推式

首选(n+1)^k-n^k=sigma(c[k][i]*n^i);

 

直接看代码里面的矩阵构造吧


wa了几次

1 组合数是要求到c[52][i]的

2 因为mod 10^9+7 所以存在的数都是可能接近int上限的  要进行+运算 所以要用long long 存储


代码:

#include<iostream>

typedef  long long inta ;

using namespace std;

struct Matrix
{
    inta  m[60][60];
    
};

inta n;    //  用来表示维度


inta   c[60][60];    //组合数

const   inta  mod=1000000007;

void init()
{
    for(inta i=0;i<=55;i++)
        c[i][0]=1;
    
    for(inta i=0;i<55;i++)
        for(inta j=0;j<=i;j++)
            c[i+1][j+1]=c[i][j+1]+c[i][j];
    
}

Matrix multi(Matrix a,Matrix b)
{
    
    Matrix ans;
    
    for(inta i=0;i<n;i++)
        for(inta j=0;j<n;j++)
        {
            inta   c=0;
            for(inta k=0;k<n;k++)
                c=(c+a.m[i][k]*b.m[k][j])%mod;
            
            ans.m[i][j]=c;
            
        }
    
    return ans;
    
}

Matrix quick_mod(Matrix a,inta b)
{
    Matrix  ans;
    
    Matrix  p=a;
    
    for(inta i=0;i<n;i++)
        for(inta j=0;j<n;j++)
            ans.m[i][j]=(i==j?1:0);
    
    while(b)
    {
        if(b&1)
        {
            ans=multi(ans, p);
            b--;
        }
        
        b>>=1;
        p=multi(p, p);
        
    }
    
    return ans;
    
    
}

class  SumOfPowers
{
    public :
    inta value(inta nn,inta k)
    {
        init();
        n=k+2;
        
        Matrix   A;
        
        for(inta i=0;i<n;i++)      //  so  important
            for(inta j=0;j<n;j++)
                A.m[i][j]=0;
        
        
        
        for(inta i=0;i<k+1;i++)
            for(inta j=0;j<=i;j++)
                A.m[i][j]=c[i][j]%mod;
        
        for(inta i=0;i<k+1;i++)
            A.m[k+1][i]=c[k][i]%mod;
        
        A.m[k+1][k+1]=1;
        
        
        A=quick_mod(A, nn-1);
        
        inta   ans=0;
        for(inta i=0;i<k+2;i++)
            ans=(ans+A.m[k+1][i])%mod;
        
        
        return ans;
    }
};



int  main()
{
    
   
    
    inta  nn,k;
    cin>>nn>>k;
    
    
    SumOfPowers  obj;
    
    cout<<obj.value(nn, k)<<endl;
    
    
}

tc上提交没有main()



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值