题解:
首先知道我们每一个球的扩散是只向四个方向扩散,所以我们新产生的贡献分成了两部分,一部分是复制一份移动四个方向,然后移动的时候在新的位置上加上坐标的净增长值就是这一次的坐标总和了。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e4+10;
int a[N],b[N];
const int mod=1e9+7;
struct Matrix
{
long long a[2][2];
Matrix(long long a1 = 1, long long a2 = 0, long long a3 = 0, long long a4 = 1)
{a[0][0] = a1; a[0][1] = a2; a[1][0] = a3; a[1][1] = a4;}
long long * operator[](int i) {return a[i];}
Matrix operator*(Matrix b){
Matrix tmp(0, 0, 0, 0);
for (int i = 0; i < 2; ++i)
for (int j = 0; j < 2; ++j)
for (int k = 0; k < 2; ++k)
tmp[i][j] = (tmp[i][j] + a[i][k] * b[k][j]) % mod;
return tmp;
}
Matrix power(long long n){
Matrix ans, tmp(*this);
while (n){
if (n & 1) ans = ans * tmp;
tmp = tmp * tmp;
n = n >> 1;
}
return ans;
}
};
void solve()
{
int n,m,x0,y0; cin>>n>>m>>x0>>y0;
x0=(x0%mod+mod)%mod;
y0=(y0%mod+mod)%mod;
int u,d,l,r;
for(int i=0;i<m;i++){
cin>>u>>d>>l>>r;
a[i]=1+u+d+l+r;
b[i]=u-d-l+r;
}
Matrix base;
for(int i=0;i<m;i++) {
base=base*Matrix(a[i],0,b[i],a[i]);
}
base=base.power(n/m);
for(int i=0;i<n%m;i++){
base=base*Matrix(a[i],0,b[i],a[i]);
}
base=base*Matrix(1,0,(x0+y0),0);
cout<<base.a[1][0]%mod<<'\n';
// cout<<(base[1][0]+base[1][1]*(x0+y0))%mod<<'\n';
}
signed main()
{
int t; cin>>t;
while(t--) solve();
}