2017暑期ACM俱乐部个人训练赛第5场 G.礼物 (矩阵快速幂)
问题 G: 礼物
时间限制: 5 Sec 内存限制: 512 MB提交: 76 解决: 23
[提交][状态][讨论版]
题目描述
热情好客的小猴请森林中的朋友们吃饭,他的朋友被编号为 1∼N,每个到来的朋友都会带给他一些礼物:香蕉。其中,第一个朋友会带给他1个香蕉,之后,每一个朋友到来以后,都会带给他之前所有人带来的礼物个数再加他的编号的K次方那么多个。所以,假设 K=2,前几位朋友带来的礼物个数分别是:
1,5,15,37,83,…
假设 K=3,前几位朋友带来的礼物个数分别是:
1,9,37,111,…
现在,小猴好奇自己到底能收到第 N 个朋友多少礼物,因此拜托于你了。
已知 N,K,请输出第 N 个朋友送的礼物个数 mod 1000000007。
1,5,15,37,83,…
假设 K=3,前几位朋友带来的礼物个数分别是:
1,9,37,111,…
现在,小猴好奇自己到底能收到第 N 个朋友多少礼物,因此拜托于你了。
已知 N,K,请输出第 N 个朋友送的礼物个数 mod 1000000007。
输入
第一行,两个整数 N,K。
输出
一个整数,表示第N个朋友送的礼物个数 mod 1000000007。
样例输入
4 2
样例输出
37
提示
100% 的数据:N≤1018,K≤10。
123
分析: 对于 第n 个人说 送的数目 an = S(n-1) +n^k; 则 前 n 个人送的总数目 S(N) = S(N-1) + aN; 于是有 S(N)= 2*S(N-1) + n^k;
构造矩阵:
于是 先打表 k的组合数; 然后 进行矩阵快速幂;
套模板
代码;
#include <iostream> #include <cstring> #include <queue> #include <algorithm> #include <stdio.h> #include <cmath> #include <string> #include <stack> typedef long long ll; const int MOD=1000000007; const int N =20; const int MAXN=11; using namespace std; ll c[20][20]; ll n; int k; ll myc(int n,int r) { ll sum=1; for(int i=1;i<=r;i++) sum=sum*(n+1-i)/i; return sum; } void init_tab() { memset(c,0,sizeof(c)); for(int i=1;i<=10;i++) for(int j=0;j<=i;j++) { c[i][j]=myc(i,j); } // for(int i=1;i<=10;i++) // { // for(int j=0;j<=i;j++) // printf("%d ",c[i][j]); // printf("\n"); // } } struct Matrix{ ll arr[N][N]; void init() { memset(arr,0,sizeof(arr)); for(int i=0;i<MAXN;i++) arr[i][i]=1;//初始化 } void iinit() { memset(arr,0,sizeof(arr)); arr[0][0]=2; for(int i=1;i<=MAXN;i++) arr[0][i]=arr[1][i]=c[k][i-1]; for(int j=2;j<=MAXN;j++) for(int i=2;i<=MAXN;i++) { arr[j][i+j-2]=c[k-j+1][i-2]; } // for(int j=0;j<=MAXN;j++) // { // for(int i=0;i<=MAXN;i++) // printf("\t%lld ",arr[j][i]); // cout<<endl; // // } } void show() { for(int j=0;j<=MAXN;j++) { for(int i=0;i<=MAXN;i++) printf("\t%lld ",arr[j][i]); cout<<endl; } } }A; Matrix mul(Matrix X,Matrix Y)// 矩阵乘法 { Matrix ans; for(int i=0;i<MAXN;i++) for(int j=0;j<MAXN;j++){ ans.arr[i][j]=0; for(int k=0;k<MAXN;k++){ ans.arr[i][j]+=X.arr[i][k]*Y.arr[k][j]; ans.arr[i][j]%=MOD; } } return ans; } Matrix Q_pow(Matrix B,ll n)// 矩阵快速幂 { Matrix ans; ans.init(); while(n) { if(n&1) ans=mul(ans,B); n>>=1; B=mul(B,B); } return ans; } int main() { init_tab(); scanf("%lld %d",&n,&k); { Matrix ans; if(n<=1) { printf("1\n"); return 0; } ans.iinit(); ans=Q_pow(ans,n-1); ll res=0; for(int i=0;i<=k;i++) res+=(ans.arr[0][i])%MOD; printf("%lld\n",res%MOD); //ans.show(); } return 0; }
岂曰无衣?与子同袍。王于兴师,修我戈矛。与子同仇!
岂曰无衣?与子同泽。王于兴师,修我矛戟。与子偕作!
岂曰无衣?与子同裳。王于兴师,修我甲兵。与子偕行!