【SNOI2017 DAY1】礼物

【SNOI2017 DAY1】礼物

虽然是一道水题 但由于我对这种类型的矩阵过于生疏 还是要写一篇题解巩固一下

直接矩乘吧

数据范围非常之大 完全没有其它想法 一定是和二分有关(当然你也可以背公式)

假设前面的人一共送了 S S ,那么当前这个人送的就是 S+ii
当前的和就是 S2+ii S ∗ 2 + i ∗ i

因此我们给定一个一维矩阵

[I0,i1,i2,i3......ik,S] [ I 0 , i 1 , i 2 , i 3 . . . . . . i k , S ]

为什么这样子定矩阵呢??
因为

(i+1)k=C0ki01n+C1ki112...+Ckkik10 ( i + 1 ) k = C k 0 ∗ i 0 1 n + C k 1 ∗ i 1 1 2 . . . + C k k i k 1 0

1 1 全部忽略 我们就能够得到 从 ik (i+1)k ( i + 1 ) k 的各个项的系数
其中包含了 i1,i2,i3 i 1 , i 2 , i 3 这样的项
所以我们也需要把它们求出来
而对应每一个元素对于这每一项的系数就是如上的组合数
构造出来的系数矩阵
1,C01,C02,C03,C04,C05.... 1 , C 1 0 , C 2 0 , C 3 0 , C 4 0 , C 5 0 . . . .
0,C11,C12,C13,C14,C15.... 0 , C 1 1 , C 2 1 , C 3 1 , C 4 1 , C 5 1 . . . .
0,0,C22,C23,C24,C25.... 0 , 0 , C 2 2 , C 3 2 , C 4 2 , C 5 2 . . . .
........ . . . . . . . .

然后单独取出 S S 的系数
对于 ik 1 1
对于 S 2 2

最后把 Sik 相加即为结果

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const long long mod=1e9+7;

int S;

struct mat
{
    long long x[123][123];
    mat(){memset(x,0,sizeof(x));}
    mat operator*(mat &B)const
    {
        mat C;
        for(int a=0;a<S;a++)
        for(int b=0;b<S;b++)
        for(int mid=0;mid<S;mid++)
            C.x[a][b]=(C.x[a][b]+x[a][mid]*B.x[mid][b])%mod;
        return C;
    }
};

long long C[123][123];

void GetC(int n)
{
    C[0][0]=C[1][0]=C[1][1]=1;
    for(int i=1;i<=n;i++)
    {
        C[i][0]=1;
        for(int j=1;j<=n;j++)
            C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
    }
}

mat KSM(mat A,mat B,long long T)
{
    while(T)
    {
        if(T&1)A=A*B;
        T>>=1;
        B=B*B;
    }
    return A;
}

long long N;int K;
mat A,B;

int main()
{
    //freopen("In.txt","r",stdin);
    scanf("%lld%d",&N,&K);
    GetC(K);
    for(int i=0;i<=K;i++)
    for(int j=0;j<=i;j++)
        B.x[j][i]=C[i][j];
    S=K+3;
    B.x[K][K+1]=B.x[K+2][K+1]=1;
    B.x[K][K+2]=1;B.x[K+2][K+2]=2;
    //A.x[0][0]=A.x[0][K+1]=1;
    for(int i=0;i<=K+1;i++)A.x[0][i]=1; 
    A=KSM(A,B,N);
    printf("%lld",A.x[0][K+1]);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值