【SNOI2017 DAY1】礼物

【SNOI2017 DAY1】礼物

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

直接矩乘吧

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

假设前面的人一共送了 S S ,那么当前这个人送的就是 S+ii S + i ∗ i
当前的和就是 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 k (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 i k 1 1
对于 S S 2 2

最后把 Sik S 、 i k 相加即为结果

#include 
#include 
#include 
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;afor(int b=0;bfor(int mid=0;midreturn 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]);
}

你可能感兴趣的:(矩阵,数论)