bzoj 5015 [Snoi2017]礼物 矩阵乘法

5015: [Snoi2017]礼物

Time Limit: 15 Sec  Memory Limit: 512 MB
Submit: 163  Solved: 115
[Submit][Status][Discuss]

Description

热情好客的请森林中的朋友们吃饭,他的朋友被编号为 1~N,每个到来的朋友都会带给他一些礼物:。其中,第
一个朋友会带给他 1 个,之后,每一个朋友到来以后,都会带给他之前所有人带来的礼物个数再加他的编号的 K 
次方那么多个。所以,假设 K=2,前几位朋友带来的礼物个数分别是:1,5,15,37,83假设 K=3,前几位朋友带来的
礼物个数分别是:1,9,37,111现在,好奇自己到底能收到第 N 个朋友多少礼物,因此拜托于你了。已知 N,K请输
出第 N 个朋友送的礼物个数 mod1000000007。
 

Input

第一行,两个整数 N,K
N≤10^18,K≤10
 

Output

一个整数,表示第 N 个朋友送的礼物个数 mod1000000007。 
 

Sample Input

4 2

Sample Output

37

 

%%cqzhangyu https://www.cnblogs.com/CQzhangyu/p/7500294.html

很好想的吧。

 1 #include<cstring>
 2 #include<cmath>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #include<iostream>
 6 
 7 #define ll long long
 8 #define mod 1000000007
 9 #define N 20
10 
11 #define Wb putchar(' ')
12 #define We putchar('\n')
13 using namespace std;
14 inline ll read()
15 {
16     ll x=0,f=1;char ch=getchar();
17     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
18     while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
19     return x*f;
20 }
21 inline void write(ll x)
22 {
23     if(x<0) putchar('-'),x=-x;
24     if (x==0) putchar(48);
25     int num=0;char c[15];
26     while(x) c[++num]=(x%10)+48,x/=10;
27     while(num) putchar(c[num--]);
28 }
29 
30 ll n,K;
31 ll c[N][N];
32 struct Node
33 {
34     ll a[N][N];
35     void init()
36     {
37         for (int i=1;i<=K+2;i++)
38             for (int j=1;j<=K+2;j++)
39                 a[i][j]=0;
40     }
41     friend Node operator*(Node x,Node y)
42     {
43         Node t;t.init();
44         for (int i=1;i<=K+2;i++)
45             for (int j=1;j<=K+2;j++)
46                 for (int k=1;k<=K+2;k++)
47                     t.a[i][j]=(t.a[i][j]+x.a[i][k]*y.a[k][j])%mod;
48         return t;
49     }
50 }dw,a,b;
51 
52 void fast_pow(Node &ans,Node a,ll b)
53 {
54     while(b)
55     {
56         if (b&1) ans=ans*a;
57         a=a*a;
58         b>>=1;
59     }
60 }
61 int main()
62 {
63     n=read(),K=read();
64     for (int i=0;i<=K;i++)c[i][0]=1;
65     for (int i=1;i<=K;i++)
66         for (int j=1;j<=i;j++)
67             c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
68     for (int i=1;i<=K+2;i++)
69         a.a[1][i]=b.a[1][i]=1;
70     for (int i=2;i<=K+2;i++)
71         for (int j=2;j<=K+2;j++)
72             dw.a[i][j]=c[j-2][i-2];
73     dw.a[1][1]=2;
74     for (int i=2;i<=K+2;i++)
75         dw.a[i][1]=c[K][i-2];
76     if (n==1) write(1);
77     else 
78     {
79         fast_pow(a,dw,n-2),fast_pow(b,dw,n-1);
80         ll ans=b.a[1][1]-a.a[1][1];
81         write((ans%mod+mod)%mod);
82     }
83 }

猜你喜欢

转载自www.cnblogs.com/fengzhiyuan/p/8983637.html
今日推荐