题目链接
https://nanti.jisuanke.com/t/41411
思路
怎么说呢,这题就是让你先解模线性方程组,然后用矩阵快速幂算数列前n项和。虽说跟模板题很接近但也有160多行代码,我觉得写起来还是很繁琐的,调试起来也不简单。这里不多说了,就把这题当作高斯消元模板记录一下吧。
代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll maxn=80;
const ll mod=1e9+7;
typedef ll Mat[maxn][maxn];
ll p[maxn],f[maxn*2],sum[maxn*2],n,k;
Mat A;
void read(ll &x)
{
ll f=1;x=0;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
x*=f;
}
//高斯消元部分
//填数
void solve(){
memset(A,0,sizeof(A));
ll cur=k+1;
//cout<<"f"<<endl;
for(ll i=0;i<k;i++){
for(ll j=0;j<k;j++){
A[i][j]=f[cur-1-j];
}
A[i][k]=f[cur];
cur++;
}
}
ll pow_mod(ll x, ll k, ll mod) {
ll ret=1;
while(k){
if(k&1)
ret=ret*x%mod;
x=x*x%mod;
k>>=1;
}
return ret;
}
ll inv(ll v,ll modd){
return pow_mod(v%modd,modd-2,modd);
}
void gauss_elimin(){
for(ll i=0;i<k;i++){
ll r=i;
for(ll j=i+1;j<k;j++)
if (A[r][i]<A[j][i])
r=j;
if(r!=i){
for(ll j=0;j<=k;j++)
swap(A[i][j],A[r][j]);
}
if(A[i][i]==0)
continue;
for(ll l=i+1;l<k;l++){
ll f=A[l][i]*inv(A[i][i],mod)%mod;
for(ll j=i;j<=k;j++)
A[l][j]=((A[l][j]-A[i][j]*f)%mod+mod)%mod;
}
}
for(ll i=k-1;i>=0;i--){
for(ll j=i+1;j<k;j++)
A[i][k]=((A[i][k]-A[i][j]*A[j][k])%mod+mod)%mod;
A[i][k]=A[i][k]*inv(A[i][i],mod)%mod;
}
for(ll i=0;i<k;i++)p[i]=A[i][k];
//for(ll i=0;i<k;i++)cout<<p[i]<<" ";cout<<endl;
}
//矩阵快速幂部分
int len;
struct matt{
ll mt[101][101];
matt(){
memset(mt,0,sizeof(mt));
}
};
matt a,e;
matt Mul(matt x,matt y) //矩阵乘
{
matt c;
for(ll i=1;i<=len;i++)
for(ll j=1;j<=len;j++)
c.mt[i][j]=0;
for(ll i=1;i<=len;i++)
for(ll j=1;j<=len;j++)
for(ll k=1;k<=len;k++)
c.mt[i][j]=c.mt[i][j]%mod+x.mt[i][k]*y.mt[k][j]%mod;
return c;
}
matt pow(matt x,ll y) //矩阵快速幂
{
matt ans=e;
while(y)
{
if(y&1)
ans=Mul(ans,x);
x=Mul(x,x);
y>>=1;
}
return ans;
}
//填写矩阵
ll work(){
ll i,j;
for(i=1;i<=len;i++)
e.mt[i][i]=1;
memset(a.mt,0,sizeof(a.mt));
for(i=1;i<=len;i++){
if(i==1){
a.mt[1][1]=1;
for(j=2;j<=len;j++){
a.mt[1][j]=p[j-2];
}
continue;
}
if(i==2){
for(j=2;j<=len;j++){
a.mt[2][j]=p[j-2];
}
continue;
}
a.mt[i][j-1]=1;
}
matt al=pow(a,n-2*k);
ll xx[maxn],x[maxn],ans=0;
for(i=1;i<=k;i++)xx[i]=f[k+i];xx[k+1]=sum[2*k];
for(i=1;i<=len;i++)x[len-i+1]=xx[i];
for(i=1;i<=len;i++){
ans+=al.mt[1][i]*x[i];
ans%=mod;
}
return ans;
}
int main(){
ll cas;
read(cas);
while(cas--){
read(k);read(n);len=k+1;
for(ll i=1;i<=2*k;i++)read(f[i]);
memset(sum,0,sizeof(sum));
for(ll i=1;i<=2*k;i++){
sum[i]=sum[i-1]+f[i];
sum[i]%=mod;
}
if(n<=2*k){
cout<<sum[n]<<endl;
continue;
}
solve();
gauss_elimin();
cout<<work()<<endl;
}
return 0;
}