233 Matrix
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 503 Accepted Submission(s): 316
For each case, the first line contains two postive integers n,m(n ≤ 10,m ≤ 10 9). The second line contains n integers, a 1,0,a 2,0,...,a n,0(0 ≤ a i,0 < 2 31).
1 1 1 2 2 0 0 3 7 23 47 16
234 2799 72937
题意:一个矩阵,a(0,1)=233,a(0,2)=2333,a(0,3)=23333,a(0,4)=233333.......,告诉你n,m,并且给你a(1,0),a(2,0)......a(n,0)。
a(i,j)=a(i-1,j)+a(i,j-1),1<=i,j。求a(n,m)。n<=10,m<=1000000000。
题解:由于n很小,m很大,所以容易想到构造矩阵,并用矩阵二分幂来解。我们用l1,l2....ln,表示当前列的值,初始值为a(1,0),....a(n,0)。设当前列的下一列为b1,b2,....bn。那么容易得出b1=l1+2333..,b2=l1+l2+2333..,b3=l1+l2+2333...,bn=l1+l2+..ln+2333..。而下一列的23333=当前列2333*10+3。那么我们可以这样构造矩阵,假设n==4。
l1 1 0 0 0 1 0 b1
l2 1 1 0 0 1 0 b2
l3 * 1 1 1 0 1 0 = b3
l4 1 1 1 1 1 0 b4
233.. 0 0 0 0 10 3 233..*10+3
1 0 0 0 0 0 1 1
这样我们就可以用当前列推出下一列,我们就可以用矩阵二分幂求解了。
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<vector>
#include<iostream>
#include<string.h>
#include<string>
#include<math.h>
#include<stdlib.h>
#define inff 0x3fffffff
#define eps 1e-8
#define nn 210000
#define mod 10000007
typedef __int64 LL;
using namespace std;
int N,M;
LL aa[20];
const int MAXN=20;
const int MAXM=20;
struct Matrix
{
int n,m;
LL a[MAXN][MAXM];
void clear()
{
n=m=0;
memset(a,0,sizeof a);
}
Matrix operator *(const Matrix &b) const
{
Matrix tmp;
tmp.clear();
tmp.n=n; tmp.m=b.m;
for(int k=0; k<m; k++)
for(int i=0; i<n; i++)
for(int j=0; j<b.m; j++)
{
tmp.a[i][j]+=(a[i][k]*b.a[k][j])%mod;
tmp.a[i][j]%=mod;
}
return tmp;
}
}ma,ans;
Matrix operator ^(Matrix x,int p)
{
Matrix ret;
ret.clear();
ret.n=x.n; ret.m=x.m;
for(int i=0; i<x.n; i++)
for(int j=0; j<x.m; j++)
ret.a[i][j] = (i == j ? 1 : 0);
while(p)
{
if(p%2) ret = ret * x;
x = x * x;
p /= 2;
}
return ret;
}
int main()
{
int i,j;
while(scanf("%d%d",&N,&M)!=EOF)
{
for(i=0;i<N;i++)
{
scanf("%I64d",&aa[i]);
aa[i]%=mod;
}
ma.clear();
ma.n=ma.m=N+2;
for(i=0;i<N;i++)
{
for(j=0;j<=i;j++)
ma.a[i][j]=1;
ma.a[i][N]=1;
}
ma.a[N][N]=10;
ma.a[N][N+1]=3;
ma.a[N+1][N+1]=1;
ans.clear();
ans.n=N+2,ans.m=1;
for(i=0;i<N;i++)
ans.a[i][0]=aa[i];
ans.a[N][0]=233;
ans.a[N+1][0]=1;
ans=(ma^M)*ans;
printf("%I64d\n",ans.a[N-1][0]);
}
return 0;
}
看了大神的代码,只跑了31ms,好像直接推出了公式,orz。。。。先贴在这里,有空再学学。
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<vector>
#include<iostream>
#include<string.h>
#include<string>
#include<math.h>
#include<stdlib.h>
#define inff 0x3fffffff
#define eps 1e-8
#define nn 210000
#define mod 10000007
typedef __int64 LL;
using namespace std;
int N,M;
LL aa[20];
const int MAXN=20;
const int MAXM=20;
struct Matrix
{
int n,m;
LL a[MAXN][MAXM];
void clear()
{
n=m=0;
memset(a,0,sizeof a);
}
Matrix operator *(const Matrix &b) const
{
Matrix tmp;
tmp.clear();
tmp.n=n; tmp.m=b.m;
for(int k=0; k<m; k++)
for(int i=0; i<n; i++)
for(int j=0; j<b.m; j++)
{
tmp.a[i][j]+=(a[i][k]*b.a[k][j])%mod;
tmp.a[i][j]%=mod;
}
return tmp;
}
}ma,ans;
Matrix operator ^(Matrix x,int p)
{
Matrix ret;
ret.clear();
ret.n=x.n; ret.m=x.m;
for(int i=0; i<x.n; i++)
for(int j=0; j<x.m; j++)
ret.a[i][j] = (i == j ? 1 : 0);
while(p)
{
if(p%2) ret = ret * x;
x = x * x;
p /= 2;
}
return ret;
}
int main()
{
int i,j;
while(scanf("%d%d",&N,&M)!=EOF)
{
for(i=0;i<N;i++)
{
scanf("%I64d",&aa[i]);
aa[i]%=mod;
}
ma.clear();
ma.n=ma.m=N+2;
for(i=0;i<N;i++)
{
for(j=0;j<=i;j++)
ma.a[i][j]=1;
ma.a[i][N]=1;
}
ma.a[N][N]=10;
ma.a[N][N+1]=3;
ma.a[N+1][N+1]=1;
ans.clear();
ans.n=N+2,ans.m=1;
for(i=0;i<N;i++)
ans.a[i][0]=aa[i];
ans.a[N][0]=233;
ans.a[N+1][0]=1;
ans=(ma^M)*ans;
printf("%I64d\n",ans.a[N-1][0]);
}
return 0;
}