Problem:
Payroll
PCK company has $N$ salaried staff and they have specific ID numbers that run from $0$ to $N-1$. The company provides $N$ types of work that are also identified by ID numbers from $0$ to $N-1$. The time required to complete work $j$ is $t_j$.
To get each of the working staff to learn as many types of work as possible, the company shifts work assignment in the following fashion.
On the $d$-th day of a shift (the first day is counted as $0$th day), work $j$ is assigned to the staff $(j + d) \% N$, where the notation $p \% q$ indicates the remainder when $p$ is divided by $q$.
Salaries in the PCK company are paid on a daily basis based on the hourly rate. When a staff whose hourly rate is $a$ carries out work $j$, his/her salary will amount to $a \times t_j$. The initial hourly rate for a staff $i$ is $s_i$ yen. To boost staff’s motivation, the company employs a unique scheme for raising hourly rates. The promotion scheme table of the company contains a list of factors $f_k$ ($0 \leq k \leq M-1$), and the hourly rate of a staff is raised based on the following rule.
At the completion of the $d$-th day’s work (the first day is counted as the $0$th day), the hourly rate of the staff with ID number $d \% N$ is raised by $f_{(d \% M)}$ yen. The salary raise takes effect after the day’s pay has been made.
As the person in charge of accounting in PCK company, you have to calculate the total amount of pay for $D$ days from the $0$-th day.
Make a program to work out the total amount of salary given the following information: initial hourly rate of each staff, hours required to complete a job, a table of promotion coefficients, and the number of days. Because the total may become excessively large, report the remainder when the total salary amount is divided by $1,000,000,007(= 10^9 + 7)$.
Input
The input is given in the following format.
$N$ $M$ $D$
$s_0$ $s_1$ $...$ $s_{N-1}$
$t_0$ $t_1$ $...$ $t_{N-1}$
$f_0$ $f_1$ $...$ $f_{M-1}$
The first line provides the number of working staff and types of work $N$ ($1 \leq N \leq 100$), the number of factors $M$ ($1 \leq M \leq 100$)and the number of days $D$ ($1 \leq D \leq 10^{15}$). Note that $M + N$ is equal to or less than 100. The second line provides the initial hourly rate for each staff $s_i$ ($1 \leq s_i \leq 10^8$) as integers. The third line provides the hours $t_j$ ($1 \leq t_j \leq 10^8$) required to complete each type of job as integers. The fourth line lists the factors $f_k$ ($1 \leq f_k \leq 10^8$) in the promotion scheme table.
Output
Output the total amount of the salary.
Sample Input 1
3 2 2
3 2 1
1 2 3
1 2
Sample Output 1
26
Sample Input 2
3 2 5
3 2 1
1 2 3
1 2
Sample Output 2
91

Submitted solutions:

code_snippet: #ifdef LOGX
#define _GLIBCXX_DEBUG
#endif
#include<bits/stdc++.h>
using namespace std;

using ll=long long;
#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define rep2(i,s,n) for(int i=int(s);i<(int)(n);i++)
#define all(a) (a).begin(),(a).end()
#define rall(a) (a).rbegin(),(a).rend()
#define vv vector
const int big=1e9+7;
//const int big=998244353;
const char newl='\n';
const int inf=1e9+10;
const ll INF=ll(1e18)+10;
const int dx[]={1,0,-1,0};
const int dy[]={0,1,0,-1};

struct mint{
    ll x;
    mint(ll xx=0):x(xx){
        x%=big;
        if(x<0)x+=big;
    }
    mint& operator+=(mint r){
        x+=r.x;
        if(x>=big)x-=big;
        return *this;
    }
    mint& operator*=(mint r){
        x*=r.x;
        x%=big;
        return *this;
    }
    friend mint operator+(mint l,mint r){
        l+=r;
        return l;
    }
    friend mint operator*(mint l,mint r){
        return l*=r;
    }
    friend ostream& operator<<(ostream &os,const mint &r){
        os << r.x;
        return os;
    }
};

template<typename T>
struct matrix{
    int n;
    vector<vector<T>> vec;
    matrix(int nn):n(nn),vec(nn,vector<T>(nn)){}
    friend matrix<T> operator*(const matrix &l,const matrix &r){
        matrix<T> res(l.n);
        /*
        rep(i,l.n)rep(k,l.n)rep(j,l.n){
            res.vec[i][j]+=l.vec[i][k]*r.vec[k][j];
        }
        */
        const int n=l.n-2;
        rep(i,n+1)rep(k,l.n){
            res.vec[i][n+1]+=l.vec[i][k]*r.vec[k][n+1];
        }
        rep(j,n)rep(k,l.n){
            res.vec[n][j]+=l.vec[n][k]*r.vec[k][j];
        }
        rep(j,l.n)res.vec[j][j]=1;
        return res;
    }
    friend vector<T> operator*(const matrix &l,const vector<T> &r){
        vector<T> res(l.n);
        rep(i,l.n)rep(j,l.n){
            res[i]+=l.vec[i][j]*r[j];
        }
        return res;
    }
};

template<typename T>
T exp(T x,ll y,const T e){
    T res=e;
    while(y){
        if(y&1)res=res*x;
        x=x*x;
        y>>=1;
    }
    return res;
}

int lcm(int a,int b){
    return a/__gcd(a,b)*b;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(30);

    int n,m;
    ll d;
    cin >> n >> m >> d;
    vector<mint> s(n);
    rep(i,n)cin >> s[i].x;
    vector<int> t(n);
    rep(i,n)cin >> t[i];
    vector<int> f(m);
    rep(i,m)cin >> f[i];
    vector<matrix<mint>> vec(lcm(n,m),matrix<mint>(n+2));
    //vec[i]:i日目開始時からi日目終了時への遷移
    rep(i,lcm(n,m)){
        rep(j,n+2)vec[i].vec[j][j]=1;
        vec[i].vec[i%n][n+1]=f[i%m];
        rep(j,n)vec[i].vec[n][(j+i)%n]=t[j];
    }
    matrix<mint> res(n+2);
    rep(i,n+2)res.vec[i][i]=1;
    auto all_prod=res,rem=res;
    rep(i,vec.size()){
        all_prod=vec[i]*all_prod;
        if(i+1==d%vec.size())rem=all_prod;
    }
    res=rem*exp(all_prod,d/vec.size(),res);

    s.resize(n+2);
    s[n]=0;
    s[n+1]=1;
    s=res*s;
    cout << s[n].x << newl;
}
accuracy: 1
time_ms: 50
memory_kb: 60408
final_rank: 2

code_snippet: #line 1 "a.cpp"
#include<iostream>
using namespace std;
#line 3 "/home/kotatsugame/library/math/modint.cpp"
#include<utility>
template<int m>
struct modint{
	unsigned int x;
	constexpr modint()noexcept:x(){}
	template<typename T>
	constexpr modint(T x_)noexcept:x((x_%=m)<0?x_+m:x_){}
	constexpr unsigned int val()const noexcept{return x;}
	constexpr modint&operator++()noexcept{if(++x==m)x=0;return*this;}
	constexpr modint&operator--()noexcept{if(x==0)x=m;--x;return*this;}
	constexpr modint operator++(int)noexcept{modint res=*this;++*this;return res;}
	constexpr modint operator--(int)noexcept{modint res=*this;--*this;return res;}
	constexpr modint&operator+=(const modint&a)noexcept{x+=a.x;if(x>=m)x-=m;return*this;}
	constexpr modint&operator-=(const modint&a)noexcept{if(x<a.x)x+=m;x-=a.x;return*this;}
	constexpr modint&operator*=(const modint&a)noexcept{x=(unsigned long long)x*a.x%m;return*this;}
	constexpr modint&operator/=(const modint&a)noexcept{return*this*=a.inv();}
	constexpr modint operator+()const noexcept{return*this;}
	constexpr modint operator-()const noexcept{return modint()-*this;}
	constexpr modint pow(long long n)const noexcept
	{
		if(n<0)return pow(-n).inv();
		modint x=*this,r=1;
		for(;n;x*=x,n>>=1)if(n&1)r*=x;
		return r;
	}
	constexpr modint inv()const noexcept
	{
		int s=x,t=m,x=1,u=0;
		while(t)
		{
			int k=s/t;
			s-=k*t;
			swap(s,t);
			x-=k*u;
			swap(x,u);
		}
		return modint(x);
	}
	friend constexpr modint operator+(const modint&a,const modint&b){return modint(a)+=b;}
	friend constexpr modint operator-(const modint&a,const modint&b){return modint(a)-=b;}
	friend constexpr modint operator*(const modint&a,const modint&b){return modint(a)*=b;}
	friend constexpr modint operator/(const modint&a,const modint&b){return modint(a)/=b;}
	friend constexpr bool operator==(const modint&a,const modint&b){return a.x==b.x;}
	friend constexpr bool operator!=(const modint&a,const modint&b){return a.x!=b.x;}
	friend ostream&operator<<(ostream&os,const modint&a){return os<<a.x;}
	friend istream&operator>>(istream&is,modint&a){long long v;is>>v;a=modint(v);return is;}
};
#line 4 "a.cpp"
using mint=modint<(int)1e9+7>;
struct dat{
	mint coef,diff,plus;
	dat(){}
	dat(mint a,mint b,mint c):coef(a),diff(b),plus(c){}
	dat operator+(const dat&rhs)const{
		return dat(coef+rhs.coef,diff+rhs.diff+plus*rhs.coef,plus+rhs.plus);
	}
};
int N,M;
long D;
mint s[100],t[100],f[100];
dat dp[50][100][2500];
main()
{
	cin>>N>>M>>D;
	for(int i=0;i<N;i++)cin>>s[i];
	for(int i=0;i<N;i++)cin>>t[i];
	for(int i=0;i<M;i++)cin>>f[i];
	for(int i=0;i<N;i++)for(int j=0;j<N*M;j++)
	{
		dp[0][i][j]=dat(t[((i-j)%N+N)%N],0,(j%N==i?f[j%M]:0));
	}
	for(int k=1;k<50;k++)for(int i=0;i<N;i++)for(int j=0;j<N*M;j++)
	{
		int j2=(j+(1LL<<k-1))%(N*M);
		dp[k][i][j]=dp[k-1][i][j]+dp[k-1][i][j2];
	}
	mint ans=0;
	for(int i=0;i<N;i++)
	{
		int st=0;
		mint S=s[i];
		for(int k=0;k<50;k++)if(D>>k&1)
		{
			dat now=dp[k][i][st];
			st=(st+(1LL<<k))%(N*M);
			ans+=now.diff+S*now.coef;
			S+=now.plus;
		}
	}
	cout<<ans<<endl;
}
accuracy: 1
time_ms: 110
memory_kb: 149604
final_rank: 7

code_snippet: #include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <numeric>
#include <bitset>
#include <cmath>

static const int MOD = 1000000007;
using ll = long long;
using u32 = unsigned;
using u64 = unsigned long long;
using namespace std;

template<class T> constexpr T INF = ::numeric_limits<T>::max()/32*15+208;

template <u32 M>
struct modint {
    u32 val;
public:
    static modint raw(int v) { modint x; x.val = v; return x; }
    modint() : val(0) {}
    template <class T>
    modint(T v) { ll x = (ll)(v%(ll)(M)); if (x < 0) x += M; val = u32(x); }
    modint(bool v) { val = ((unsigned int)(v) % M); }
    modint& operator++() { val++; if (val == M) val = 0; return *this; }
    modint& operator--() { if (val == 0) val = M; val--; return *this; }
    modint operator++(int) { modint result = *this; ++*this; return result; }
    modint operator--(int) { modint result = *this; --*this; return result; }
    modint& operator+=(const modint& b) { val += b.val; if (val >= M) val -= M; return *this; }
    modint& operator-=(const modint& b) { val -= b.val; if (val >= M) val += M; return *this; }
    modint& operator*=(const modint& b) { u64 z = val; z *= b.val; val = (u32)(z % M); return *this; }
    modint& operator/=(const modint& b) { return *this = *this * b.inv(); }
    modint operator+() const { return *this; }
    modint operator-() const { return modint() - *this; }
    modint pow(long long n) const { modint x = *this, r = 1; while (n) { if (n & 1) r *= x; x *= x; n >>= 1; } return r; }
    modint inv() const { return pow(M-2); }
    friend modint operator+(const modint& a, const modint& b) { return modint(a) += b; }
    friend modint operator-(const modint& a, const modint& b) { return modint(a) -= b; }
    friend modint operator*(const modint& a, const modint& b) { return modint(a) *= b; }
    friend modint operator/(const modint& a, const modint& b) { return modint(a) /= b; }
    friend bool operator==(const modint& a, const modint& b) { return a.val == b.val; }
    friend bool operator!=(const modint& a, const modint& b) { return a.val != b.val; }
};
using mint = modint<MOD>;

template<class H, size_t SIZE>
struct SquareMatrix {
    using T = typename H::T;
    using ar = array<T, SIZE>;
    using mat = array<ar, SIZE>;
    mat A;
    SquareMatrix() = default;
    static SquareMatrix I(){
        SquareMatrix X;
        for (int i = 0; i < SIZE; ++i) {
            for (int j = 0; j < SIZE; ++j) {
                if(i == j) X[i][j] = H::one();
                else X[i][j] = H::zero();
            }
        }
        return X;
    }

    friend ar operator*=(ar &x, const SquareMatrix &Y) {
        ar ans{};
        for (int i = 0; i < SIZE; ++i) {
            for (int j = 0; j < SIZE; ++j) {
                 H::add(ans[j], H::mul(x[i], Y[i][j]));
            }
        }
        x.swap(ans);
        return x;
    }
    friend ar operator*(ar x, const SquareMatrix &Y) { return x *= Y; }

    inline const ar &operator[](int k) const{ return (A.at(k)); }
    inline ar &operator[](int k) { return (A.at(k)); }
    SquareMatrix &operator+= (const SquareMatrix &B){
        for (int i = 0; i < SIZE; ++i) {
            for (int j = 0; j < SIZE; ++j) {
                H::add((*this)[i][j], B[i][j]);
            }
        }
        return (*this);
    }

    SquareMatrix &operator-= (const SquareMatrix &B){
        for (int i = 0; i < SIZE; ++i) {
            for (int j = 0; j < SIZE; ++j) {
                H::add((*this)[i][j], -B[i][j]);
            }
        }
        return (*this);
    }

    SquareMatrix &operator*=(const SquareMatrix &B) {
        SquareMatrix C;
        for (int i = 0; i < SIZE; ++i) {
            for (int k = 0; k < SIZE; ++k) {
                for (int j = 0; j < SIZE; ++j) {
                    H::add(C[i][j],  H::mul((*this)[i][k], B[k][j]));
                }
            }
        }
        A.swap(C.A);
        return (*this);
    }

    SquareMatrix pow(ll n) const {
        SquareMatrix a = (*this), res = I();
        while(n > 0){
            if(n & 1) res *= a;
            a *= a;
            n >>= 1;
        }
        return res;
    }
    SquareMatrix operator+(const SquareMatrix &B) const {return SquareMatrix(*this) += B;}
    SquareMatrix operator-(const SquareMatrix &B) const {return SquareMatrix(*this) -= B;}
    SquareMatrix operator*(const SquareMatrix &B) const {return SquareMatrix(*this) *= B;}
};

struct SemiRing {
    using T = mint;
    static inline T mul(T x, T y){ return x * y; }
    static inline void add(T &x, T y){ x += y; }
    static inline T one(){ return 1; }
    static inline T zero(){ return 0; }
};

using ar = array<SemiRing::T, 101>;
using mat = SquareMatrix<SemiRing, 101>;

ar x;
mat A;
int main() {
    int n, m; ll d;
    cin >> n >> m >> d;
    vector<int> s(n), t(n), f(m);
    for (auto &&i : s) scanf("%d", &i);
    for (auto &&i : t) scanf("%d", &i);
    for (auto &&i : f) scanf("%d", &i);
    A[0][0] = 1;
    for (int i = 0; i < n; ++i) x[i+1] = s[i], A[i+1][0] = t[i], A[i+1][(i+n-1)%n+1] = 1;
    for (int i = 0; i < m; ++i) x[n+i+1] = f[i],  A[n+i+1][(i+m-1)%m+n+1] = 1;
    A[n+1][n] = 1;
    A = A.pow(d);
    cout << (x*A)[0].val << "\n";
    return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 3688
final_rank: 1

code_snippet: #include<bits/stdc++.h>
#include<array>
using namespace std;
using LL = long long;
using ULL = unsigned long long;
#define rep(i,n) for(int i=0; i<(n); i++)

const ULL M = 1000000007;

const int MatSz = 120;
struct Mat {
    ULL G[MatSz][MatSz] = {};
    static Mat I() {
        Mat buf;
        rep(i, MatSz) buf.G[i][i] = 1;
        return buf;
    }
};

Mat operator*(const Mat& l, const Mat& r) {
    Mat res;
    rep(i, MatSz) rep(j, MatSz) {
        rep(k, MatSz) res.G[i][j] += l.G[i][k] * r.G[k][j] % M;
        res.G[i][j] %= M;
    }
    return res;
}
Mat operator^(const Mat& a, const ULL i) {
    if (i == 0) return Mat::I();
    Mat buf = (a * a) ^ (i / 2);
    if (i % 2) buf = buf * a;
    return buf;
}

using Vec = array<ULL, MatSz>;

Vec operator*(const Vec& l, const Mat& r) {
    Vec res = {};
    rep(i, MatSz) {
        rep(j, MatSz) res[i] += l[j] * r.G[i][j] % M;
        res[i] %= M;
    }
    return res;
}

int main() {
    int N, M; ULL D; cin >> N >> M >> D;
    ULL S[100]; rep(i, N) cin >> S[i];
    ULL T[100]; rep(i, N) cin >> T[i];
    ULL F[100]; rep(i, M) cin >> F[i];

    Mat R;
    rep(i, N) R.G[i][(i + 1) % N] = 1;
    rep(i, M) R.G[N + i][N + (i + 1) % M] = 1;
    R.G[N - 1][N] = 1;
    R.G[N + M][N + M] = 1;
    rep(i, N) R.G[N + M + 1][i] = T[i];
    R.G[N + M + 1][N + M + 1] = 1;

    R = R ^ D;

    Vec X;
    rep(i, N) X[i] = S[i];
    rep(i, M) X[N + i] = F[i];
    X[N + M] = 1;
    X[N + M + 1] = 0;

    X = X * R;
    cout << X[N + M + 1] << endl;

    return 0;
}
accuracy: 1
time_ms: 130
memory_kb: 14652
final_rank: 4

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



typedef vector<ll> V;
typedef vector<V> MATRIX;

ll N,M,D;
ll SIZE;
ll S[105],T[105],F[105];

MATRIX calc(MATRIX left,MATRIX right){

	MATRIX ret(SIZE,V(SIZE));

	for(int i = 0; i < SIZE; i++){
		for(int k = 0; k < SIZE; k++)ret[i][k] = 0;
	}

	for(int row = 0; row < SIZE; row++){
		for(int col = 0; col < SIZE; col++){
			for(int a = 0; a < SIZE; a++){
				ret[row][col] += left[row][a]*right[a][col]%MOD;
			}
		}
	}

	return ret;

}

//MULTのT乗を計算する
MATRIX POW(MATRIX MULT,ll count){

	MATRIX ret(SIZE,V(SIZE));

	for(int row = 0; row < SIZE; row++){
		for(int col = 0; col < SIZE; col++){
			if(row == col)ret[row][col] = 1;
			else{
				ret[row][col] = 0;
			}
		}
	}

	while(count > 0){
		if(count%2 == 1)ret = calc(ret,MULT);
		MULT = calc(MULT,MULT);
		count /= 2;
	}

	return ret;
}


int main(){

	scanf("%lld %lld %lld",&N,&M,&D);

	for(int i = 0; i < N; i++){

		scanf("%lld",&S[i]);
	}
	for(int i = 0; i < N; i++){

		scanf("%lld",&T[i]);
	}
	for(int i = 0; i < M; i++){

		scanf("%lld",&F[i]);
	}


	SIZE = M+N+1;

	MATRIX MULT(SIZE,V(SIZE));

	for(int row = 0; row < SIZE; row++){
		for(int col = 0; col < SIZE; col++){
			MULT[row][col] = 0;
		}
	}

	MULT[0][0] = 1;
	for(int i = 0; i < N; i++){

		MULT[0][M+1+i] = T[i];
	}

	for(int row = 1; row <= M; row++){
		if(row != M){

			MULT[row][row+1] = 1;

		}else{

			MULT[row][1] = 1;
		}
	}

	for(int row = M+1; row <= M+N; row++){
		if(row != M+N){

			MULT[row][row+1] = 1;
		}else{

			MULT[row][M+1] = 1;
		}
	}
	MULT[M+N][1] = 1;

	MULT = POW(MULT,D);

	ll ans = 0;
	for(int i = 0; i < M; i++){
		ans += MULT[0][i+1]*F[i];
		ans %= MOD;
	}
	for(int i = 0; i < N; i++){
		ans += MULT[0][M+1+i]*S[i];
		ans %= MOD;
	}

	printf("%lld\n",ans);

	return 0;
}
accuracy: 1
time_ms: 140
memory_kb: 3456
final_rank: 3

code_snippet: #include <bits/stdc++.h>
#define rep(i,n)for(int i=0;i<(n);i++)
using namespace std;
typedef long long ll;

const int MOD=1000000007;

typedef vector<ll>vec;
typedef vector<vec>mat;

mat mul(mat&a, mat&b) {
	mat c(a.size(), vec(b[0].size()));
	rep(i, a.size())rep(j, b[0].size())rep(k, b.size())
		(c[i][j] += a[i][k] * b[k][j]) %= MOD;
	return c;
}
mat ppow(mat a, ll b) {
	mat res(a.size(), vec(a.size()));
	rep(i, a.size())res[i][i] = 1;
	while (b) {
		if (b & 1)res = mul(res, a);
		a = mul(a, a);
		b >>= 1;
	}
	return res;
}

int s[2000],t[200],f[200];
int main(){
	int n,m;ll d;cin>>n>>m>>d;
	rep(i,n)scanf("%d",&s[i]);
	rep(i,n)scanf("%d",&t[i]);
	rep(i,m)scanf("%d",&f[i]);
	mat A(n+m+1,vec(n+m+1));
	rep(i,n){
		A[i][(i+1)%n]=1;
	}
	rep(i,m){
		A[i+n][n+(i+1)%m]=1;
	}
	rep(i,n){
		A[n+m][i]=t[i];
	}
	A[n+m][n+m]=1;
	A[n-1][n]=1;
	mat B(n+m+1,vec(1));
	rep(i,n)B[i][0]=s[i];
	rep(i,m)B[n+i][0]=f[i];
	auto res=ppow(A,d);
	res=mul(res,B);
	cout<<res[n+m][0]<<endl;
}
accuracy: 1
time_ms: 240
memory_kb: 3436
final_rank: 6

code_snippet: #include<bits/stdc++.h>
using namespace std;
using Int = long long;
template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}


template<typename K>
struct Matrix{
  typedef vector<K> arr;
  typedef vector<arr> mat;
  mat dat;

  Matrix(size_t r,size_t c):dat(r,arr(c,K())){}
  Matrix(mat dat):dat(dat){}

  size_t size() const{return dat.size();};
  bool empty() const{return size()==0;};
  arr& operator[](size_t k){return dat[k];};
  const arr& operator[](size_t k) const {return dat[k];};
  
  static Matrix cross(const Matrix &A,const Matrix &B){
    Matrix res(A.size(),B[0].size());    
    for(int i=0;i<(int)A.size();i++)
      for(int j=0;j<(int)B[0].size();j++)
        for(int k=0;k<(int)B.size();k++)
          res[i][j]+=A[i][k]*B[k][j];
    return res;
  }

  static Matrix identity(size_t n){
    Matrix res(n,n);
    for(int i=0;i<(int)n;i++) res[i][i]=K(1);
    return res;
  }
  
  Matrix pow(long long n) const{
    Matrix a(dat),res=identity(size());
    while(n){
      if(n&1) res=cross(res,a);
      a=cross(a,a);      
      n>>=1;
    }
    return res;
  }

  template<typename T> using ET = enable_if<is_floating_point<T>::value>;
  template<typename T> using EF = enable_if<!is_floating_point<T>::value>;
  
  template<typename T, typename ET<T>::type* = nullptr>
  static bool is_zero(T x){return abs(x)<1e-8;}
  template<typename T, typename EF<T>::type* = nullptr>
  static bool is_zero(T x){return x==T(0);}

  static Matrix gauss_jordan(const Matrix &A,const Matrix &B){
    int n=A.size(),l=B[0].size();
    Matrix C(n,n+l);
    for(int i=0;i<n;i++){
      for(int j=0;j<n;j++)
        C[i][j]=A[i][j];      
      for(int j=0;j<l;j++)
        C[i][n+j]=B[i][j];
    }
    for(int i=0;i<n;i++){
      int p=i;
      for(int j=i;j<n;j++)
        if(abs(C[p][i])<abs(C[j][i])) p=j;
      swap(C[i],C[p]);
      if(is_zero(C[i][i])) return Matrix(0,0);
      for(int j=i+1;j<n+l;j++) C[i][j]/=C[i][i];
      for(int j=0;j<n;j++){
        if(i==j) continue;
        for(int k=i+1;k<n+l;k++)
          C[j][k]-=C[j][i]*C[i][k];
      }
    }
    Matrix res(n,l);
    for(int i=0;i<n;i++)
      for(int j=0;j<l;j++)
        res[i][j]=C[i][n+j];
    return res;
  }
  
  Matrix inv() const{
    Matrix B=identity(size());
    return gauss_jordan(*this,B);
  }  
};


template<typename T,T MOD = 1000000007>
struct Mint{
  T v;
  Mint():v(0){}
  Mint(signed v):v(v){}
  Mint(long long t){v=t%MOD;if(v<0) v+=MOD;}

  Mint pow(int k){
    Mint res(1),tmp(v);
    while(k){
      if(k&1) res*=tmp;
      tmp*=tmp;
      k>>=1;
    }
    return res;
  }
  
  Mint inv(){return pow(MOD-2);}
  
  Mint& operator+=(Mint a){v+=a.v;if(v>=MOD)v-=MOD;return *this;}
  Mint& operator-=(Mint a){v+=MOD-a.v;if(v>=MOD)v-=MOD;return *this;}
  Mint& operator*=(Mint a){v=1LL*v*a.v%MOD;return *this;}
  Mint& operator/=(Mint a){return (*this)*=a.inv();}
  
  Mint operator+(Mint a) const{return Mint(v)+=a;};
  Mint operator-(Mint a) const{return Mint(v)-=a;};
  Mint operator*(Mint a) const{return Mint(v)*=a;};
  Mint operator/(Mint a) const{return Mint(v)/=a;};

  Mint operator-(){return v?MOD-v:v;}

  bool operator==(const Mint a)const{return v==a.v;}
  bool operator!=(const Mint a)const{return v!=a.v;}
  
};

//INSERT ABOVE HERE
signed main(){
  int n,m;
  Int k;
  cin>>n>>m>>k;

  vector<int> s(n),t(n),f(m);
  for(int i=0;i<n;i++) cin>>s[i];
  for(int i=0;i<n;i++) cin>>t[i];
  for(int i=0;i<m;i++) cin>>f[i];
  
  using M = Mint<int>;
  using MM = Matrix<M>;

  MM dat(1+m+n,1+m+n);
  MM col(1+m+n,1);
  col[0][0]=0;
  for(int i=0;i<m;i++) col[1+i][0]=M(f[i]);
  for(int i=0;i<n;i++) col[1+m+i][0]=M(s[i]);

  dat[0][0]=1;
  for(int i=0;i<n;i++) dat[0][1+m+i]=M(t[i]);

  for(int i=0;i+1<m;i++) dat[1+i][1+i+1]=M(1);
  dat[m][1]=M(1);
  
  for(int i=0;i+1<n;i++) dat[1+m+i][1+m+i+1]=M(1);
  dat[m+n][1+m]=M(1);

  dat[m+n][1]=1;

  if(0){
    for(int i=0;i<1+m+n;i++){
      for(int j=0;j<1+m+n;j++)
        cout<<dat[i][j].v<<" ";
      cout<<endl;
    }
    for(int i=0;i<1+m+n;i++)
      cout<<col[i][0].v<<endl;
  }
  
  M sum=MM::cross(dat.pow(k),col)[0][0];

  cout<<sum.v<<endl;  
  return 0;
}
accuracy: 1
time_ms: 190
memory_kb: 3304
final_rank: 5