题意:给出矩阵的第0行(233,2333,23333,...)和第0列a1,a2,...an(n<=10,m<=10^9),给出递推式: A[i][j] = A[i-1][j] + A[i][j-1],要求A[n][m]。
数据范围:n,m(n ≤ 10,m ≤ 109).
思路:因为m ≤ 109
显然是要找到列与列的递推关系,用logn幂加速。
从递推式可以得知:a[i][j]可以由a[1...i][j-1] 递推得到,所以构造递推矩阵实现a[1...1][j-1]向a[1...1][j]的转移‘即可
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int mod = 10000007; struct mat { ll a[15][15]; mat() { memset(a,0,sizeof(a)); } }; ll I[15]; mat S; int n,m; void print(mat m) { for(int i=1;i<=n;i++,puts("")) for(int j=1;j<=n;j++) printf("%d ",m.a[i][j]); } mat mul(mat m1,mat m2) { mat ans; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(m1.a[i][j]) for(int k=1;k<=n;k++) ans.a[i][k]=( ans.a[i][k]+m1.a[i][j]*m2.a[j][k] )%mod; return ans; } mat quickmul(mat m,int k) { mat ans; for(int i=1;i<=n;i++) ans.a[i][i]=1; while(k) { if(k&1) ans=mul(ans,m); m=mul(m,m); k>>=1; } return ans; } int main() { while(~scanf("%d%d",&n,&m)) { n+=2; I[1]=23,I[n]=1; for(int i=2;i<n;i++) scanf("%I64d",&I[i]); for(int i=1;i<n;i++)//构造矩阵 { S.a[i][1]=10; for(int j=2;j<=i;j++) S.a[i][j]=1; for(int j=i+1;j<n;j++) S.a[i][j]=0; S.a[i][n]=3; } for(int i=1;i<=n;i++) S.a[n][i]=(i==n); mat t=quickmul(S,m); ll ans=0; for(int i=1;i<=n;i++) ans+=I[i]*t.a[n-1][i]; printf("%I64d\n",ans%mod); } return 0; }
时间: 2024-10-12 05:53:45