text: #include <bits/stdc++.h>
  using namespace std;
   
  using ll = long long;
  using db = long double; // or double, if TL is tight
  using str = string; // yay python! 
  
  // pairs
  using pi = pair<int,int>;
  using pl = pair<ll,ll>;
  using pd = pair<db,db>;
  #define mp make_pair
  #define f first
  #define s second
  
  #define tcT template<class T
  #define tcTU tcT, class U
  // ^ lol this makes everything look weird but I'll try it
  tcT> using V = vector<T>; 
  tcT, size_t SZ> using AR = array<T,SZ>; 
  using vi = V<int>;
  using vb = V<bool>;
  using vl = V<ll>;
  using vd = V<db>;
  using vs = V<str>;
  using vpi = V<pi>;
  using vpl = V<pl>;
  using vpd = V<pd>;
  
  // vectors
  // oops size(x), rbegin(x), rend(x) need C++17
  #define sz(x) int((x).size())
  #define bg(x) begin(x)
  #define all(x) bg(x), end(x)
  #define rall(x) x.rbegin(), x.rend() 
  #define sor(x) sort(all(x)) 
  #define rsz resize
  #define ins insert 
  #define pb push_back
  #define eb emplace_back
  #define ft front()
  #define bk back()
  
  #define lb lower_bound
  #define ub upper_bound
  tcT> int lwb(V<T>& a, const T& b) { return int(lb(all(a),b)-bg(a)); }
  tcT> int upb(V<T>& a, const T& b) { return int(ub(all(a),b)-bg(a)); }
  
  // loops
  #define FOR(i,a,b) for (int i = (a); i < (b); ++i)
  #define F0R(i,a) FOR(i,0,a)
  #define ROF(i,a,b) for (int i = (b)-1; i >= (a); --i)
  #define R0F(i,a) ROF(i,0,a)
  #define rep(a) F0R(_,a)
  #define each(a,x) for (auto& a: x)
  
  const int MOD = 1e9+7; // 998244353;
  const int MX = 2e5+5;
  const ll BIG = 1e18; // not too close to LLONG_MAX
  const db PI = acos((db)-1);
  const int dx[4]{1,0,-1,0}, dy[4]{0,1,0,-1}; // for every grid problem!!
  mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count()); 
  template<class T> using pqg = priority_queue<T,vector<T>,greater<T>>;
  
  // bitwise ops
  // also see https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html
  constexpr int pct(int x) { return __builtin_popcount(x); } // # of bits set
  constexpr int bits(int x) { // assert(x >= 0); // make C++11 compatible until USACO updates ...
  	return x == 0 ? 0 : 31-__builtin_clz(x); } // floor(log2(x)) 
  constexpr int p2(int x) { return 1<<x; }
  constexpr int msk2(int x) { return p2(x)-1; }
  
  ll cdiv(ll a, ll b) { return a/b+((a^b)>0&&a%b); } // divide a by b rounded up
  ll fdiv(ll a, ll b) { return a/b-((a^b)<0&&a%b); } // divide a by b rounded down
  
  tcT> bool ckmin(T& a, const T& b) {
  	return b < a ? a = b, 1 : 0; } // set a = min(a,b)
  tcT> bool ckmax(T& a, const T& b) {
  	return a < b ? a = b, 1 : 0; } // set a = max(a,b)
  
  tcTU> T fstTrue(T lo, T hi, U f) {
  	++hi; assert(lo <= hi); // assuming f is increasing
  	while (lo < hi) { // find first index such that f is true 
  		T mid = lo+(hi-lo)/2;
  		f(mid) ? hi = mid : lo = mid+1; 
  	} 
  	return lo;
  }
  tcTU> T lstTrue(T lo, T hi, U f) {
  	--lo; assert(lo <= hi); // assuming f is decreasing
  	while (lo < hi) { // find first index such that f is true 
  		T mid = lo+(hi-lo+1)/2;
  		f(mid) ? lo = mid : hi = mid-1;
  	} 
  	return lo;
  }
  tcT> void remDup(vector<T>& v) { // sort and remove duplicates
  	sort(all(v)); v.erase(unique(all(v)),end(v)); }
  tcTU> void erase(T& t, const U& u) { // don't erase
  	auto it = t.find(u); assert(it != end(t));
  	t.erase(it); } // element that doesn't exist from (multi)set
  
  #define tcTUU tcT, class ...U
  
  inline namespace Helpers {
  	//////////// is_iterable
  	// https://stackoverflow.com/questions/13830158/check-if-a-variable-type-is-iterable
  	// this gets used only when we can call begin() and end() on that type
  	tcT, class = void> struct is_iterable : false_type {};
  	tcT> struct is_iterable<T, void_t<decltype(begin(declval<T>())),
  	                                  decltype(end(declval<T>()))
  	                                 >
  	                       > : true_type {};
  	tcT> constexpr bool is_iterable_v = is_iterable<T>::value;
  
  	//////////// is_readable
  	tcT, class = void> struct is_readable : false_type {};
  	tcT> struct is_readable<T,
  	        typename std::enable_if_t<
  	            is_same_v<decltype(cin >> declval<T&>()), istream&>
  	        >
  	    > : true_type {};
  	tcT> constexpr bool is_readable_v = is_readable<T>::value;
  
  	//////////// is_printable
  	// // https://nafe.es/posts/2020-02-29-is-printable/
  	tcT, class = void> struct is_printable : false_type {};
  	tcT> struct is_printable<T,
  	        typename std::enable_if_t<
  	            is_same_v<decltype(cout << declval<T>()), ostream&>
  	        >
  	    > : true_type {};
  	tcT> constexpr bool is_printable_v = is_printable<T>::value;
  }
  
  inline namespace Input {
  	tcT> constexpr bool needs_input_v = !is_readable_v<T> && is_iterable_v<T>;
  	tcTUU> void re(T& t, U&... u);
  	tcTU> void re(pair<T,U>& p); // pairs
  
  	// re: read
  	tcT> typename enable_if<is_readable_v<T>,void>::type re(T& x) { cin >> x; } // default
  	tcT> void re(complex<T>& c) { T a,b; re(a,b); c = {a,b}; } // complex
  	tcT> typename enable_if<needs_input_v<T>,void>::type re(T& i); // ex. vectors, arrays
  	tcTU> void re(pair<T,U>& p) { re(p.f,p.s); }
  	tcT> typename enable_if<needs_input_v<T>,void>::type re(T& i) {
  		each(x,i) re(x); }
  	tcTUU> void re(T& t, U&... u) { re(t); re(u...); } // read multiple
  
  	// rv: resize and read vectors
  	void rv(size_t) {}
  	tcTUU> void rv(size_t N, V<T>& t, U&... u);
  	template<class...U> void rv(size_t, size_t N2, U&... u);
  	tcTUU> void rv(size_t N, V<T>& t, U&... u) {
  		t.rsz(N); re(t);
  		rv(N,u...); }
  	template<class...U> void rv(size_t, size_t N2, U&... u) {
  		rv(N2,u...); }
  
  	// dumb shortcuts to read in ints
  	void decrement() {} // subtract one from each
  	tcTUU> void decrement(T& t, U&... u) { --t; decrement(u...); }
  	#define ints(...) int __VA_ARGS__; re(__VA_ARGS__);
  	#define int1(...) ints(__VA_ARGS__); decrement(__VA_ARGS__);
  }
  
  inline namespace ToString {
  	tcT> constexpr bool needs_output_v = !is_printable_v<T> && is_iterable_v<T>;
  
  	// ts: string representation to print
  	tcT> typename enable_if<is_printable_v<T>,str>::type ts(T v) {
  		stringstream ss; ss << fixed << setprecision(15) << v;
  		return ss.str(); } // default
  	tcT> str bit_vec(T t) { // bit vector to string
  		str res = "{"; F0R(i,sz(t)) res += ts(t[i]);
  		res += "}"; return res; }
  	str ts(V<bool> v) { return bit_vec(v); }
  	template<size_t SZ> str ts(bitset<SZ> b) { return bit_vec(b); } // bit vector
  	tcTU> str ts(pair<T,U> p); // pairs
  	tcT> typename enable_if<needs_output_v<T>,str>::type ts(T v); // vectors, arrays
  	tcTU> str ts(pair<T,U> p) { return "("+ts(p.f)+", "+ts(p.s)+")"; }
  	tcT> typename enable_if<is_iterable_v<T>,str>::type ts_sep(T v, str sep) {
  		// convert container to string w/ separator sep
  		bool fst = 1; str res = "";
  		for (const auto& x: v) {
  			if (!fst) res += sep;
  			fst = 0; res += ts(x);
  		}
  		return res;
  	}
  	tcT> typename enable_if<needs_output_v<T>,str>::type ts(T v) {
  		return "{"+ts_sep(v,", ")+"}"; }
  
  	// for nested DS
  	template<int, class T> typename enable_if<!needs_output_v<T>,vs>::type 
  	  ts_lev(const T& v) { return {ts(v)}; }
  	template<int lev, class T> typename enable_if<needs_output_v<T>,vs>::type 
  	  ts_lev(const T& v) {
  		if (lev == 0 || !sz(v)) return {ts(v)};
  		vs res;
  		for (const auto& t: v) {
  			if (sz(res)) res.bk += ",";
  			vs tmp = ts_lev<lev-1>(t);
  			res.ins(end(res),all(tmp));
  		}
  		F0R(i,sz(res)) {
  			str bef = " "; if (i == 0) bef = "{";
  			res[i] = bef+res[i];
  		}
  		res.bk += "}";
  		return res;
  	}
  }
  
  inline namespace Output {
  	template<class T> void pr_sep(ostream& os, str, const T& t) { os << ts(t); }
  	template<class T, class... U> void pr_sep(ostream& os, str sep, const T& t, const U&... u) {
  		pr_sep(os,sep,t); os << sep; pr_sep(os,sep,u...); }
  	// print w/ no spaces
  	template<class ...T> void pr(const T&... t) { pr_sep(cout,"",t...); } 
  	// print w/ spaces, end with newline
  	void ps() { cout << "\n"; }
  	template<class ...T> void ps(const T&... t) { pr_sep(cout," ",t...); ps(); } 
  	// debug to cerr
  	template<class ...T> void dbg_out(const T&... t) {
  		pr_sep(cerr," | ",t...); cerr << endl; }
  	void loc_info(int line, str names) {
  		cerr << "Line(" << line << ") -> [" << names << "]: "; }
  	template<int lev, class T> void dbgl_out(const T& t) {
  		cerr << "\n\n" << ts_sep(ts_lev<lev>(t),"\n") << "\n" << endl; }
  	#ifdef LOCAL
  		#define dbg(...) loc_info(__LINE__,#__VA_ARGS__), dbg_out(__VA_ARGS__)
  		#define dbgl(lev,x) loc_info(__LINE__,#x), dbgl_out<lev>(x)
  	#else // don't actually submit with this
  		#define dbg(...) 0
  		#define dbgl(lev,x) 0
  	#endif
  
  	const clock_t beg = clock();
  	#define dbg_time() dbg((db)(clock()-beg)/CLOCKS_PER_SEC)
  }
  
  inline namespace FileIO {
  	void setIn(str s)  { freopen(s.c_str(),"r",stdin); }
  	void setOut(str s) { freopen(s.c_str(),"w",stdout); }
  	void setIO(str s = "") {
  		cin.tie(0)->sync_with_stdio(0); // unsync C / C++ I/O streams
  		// cin.exceptions(cin.failbit);
  		// throws exception when do smth illegal
  		// ex. try to read letter into int
  		if (sz(s)) setIn(s+".in"), setOut(s+".out"); // for old USACO
  	}
  }
  
  /**
   * Description: modular arithmetic operations 
   * Source: 
  	* KACTL
  	* https://codeforces.com/blog/entry/63903
  	* https://codeforces.com/contest/1261/submission/65632855 (tourist)
  	* https://codeforces.com/contest/1264/submission/66344993 (ksun)
  	* also see https://github.com/ecnerwala/cp-book/blob/master/src/modnum.hpp (ecnerwal)
   * Verification: 
  	* https://open.kattis.com/problems/modulararithmetic
   */
  
  template<int MOD, int RT> struct mint {
  	static const int mod = MOD;
  	static constexpr mint rt() { return RT; } // primitive root for FFT
  	int v; explicit operator int() const { return v; } // explicit -> don't silently convert to int
  	mint():v(0) {}
  	mint(ll _v) { v = int((-MOD < _v && _v < MOD) ? _v : _v % MOD);
  		if (v < 0) v += MOD; }
  	bool operator==(const mint& o) const {
  		return v == o.v; }
  	friend bool operator!=(const mint& a, const mint& b) { 
  		return !(a == b); }
  	friend bool operator<(const mint& a, const mint& b) { 
  		return a.v < b.v; }
  	friend void re(mint& a) { ll x; re(x); a = mint(x); }
  	friend str ts(mint a) { return ts(a.v); }
     
  	mint& operator+=(const mint& o) { 
  		if ((v += o.v) >= MOD) v -= MOD; 
  		return *this; }
  	mint& operator-=(const mint& o) { 
  		if ((v -= o.v) < 0) v += MOD; 
  		return *this; }
  	mint& operator*=(const mint& o) { 
  		v = int((ll)v*o.v%MOD); return *this; }
  	mint& operator/=(const mint& o) { return (*this) *= inv(o); }
  	friend mint pow(mint a, ll p) {
  		mint ans = 1; assert(p >= 0);
  		for (; p; p /= 2, a *= a) if (p&1) ans *= a;
  		return ans; }
  	friend mint inv(const mint& a) { assert(a.v != 0); 
  		return pow(a,MOD-2); }
  		
  	mint operator-() const { return mint(-v); }
  	mint& operator++() { return *this += 1; }
  	mint& operator--() { return *this -= 1; }
  	friend mint operator+(mint a, const mint& b) { return a += b; }
  	friend mint operator-(mint a, const mint& b) { return a -= b; }
  	friend mint operator*(mint a, const mint& b) { return a *= b; }
  	friend mint operator/(mint a, const mint& b) { return a /= b; }
  };
  
  using mi = mint<MOD,5>; // 5 is primitive root for both common mods
  using vmi = V<mi>;
  using pmi = pair<mi,mi>;
  using vpmi = V<pmi>;
  
  V<vmi> scmb; // small combinations
  void genComb(int SZ) {
  	scmb.assign(SZ,vmi(SZ)); scmb[0][0] = 1;
  	FOR(i,1,SZ) F0R(j,i+1) 
  		scmb[i][j] = scmb[i-1][j]+(j?scmb[i-1][j-1]:0);
  }
  
  mi c2(mi x) { return x*(x-1)/2; }
  
  
  /**
   * Description: A set (not multiset!) with support for finding the $n$'th
   * element, and finding the index of an element. Change \texttt{null\_type} for map.
   * Time: O(\log N)
   * Source: KACTL
     * https://codeforces.com/blog/entry/11080
   * Verification: many
   */
  
  #include <ext/pb_ds/assoc_container.hpp>
  using namespace __gnu_pbds;
  tcT> using Tree = tree<T, null_type, less<T>, 
  	rb_tree_tag, tree_order_statistics_node_update>; 
  #define ook order_of_key
  #define fbo find_by_order
  
  void treeExample() {
  	Tree<int> t, t2; t.insert(8);
  	auto it = t.insert(10).f; assert(it == t.lb(9));
  	assert(t.ook(10) == 1 && t.ook(11) == 2 && *t.fbo(0) == 8);
  	t.join(t2); // assuming T < T2 or T > T2, merge t2 into t
  }
  
  /**
  int atMost(Tree<pi>& T, int r) { 
  	return T.ook({r,MOD}); }
  int getSum(Tree<pi>& T, int l, int r) { 
  	return atMost(T,r)-atMost(T,l-1); }
  */
  
  mi smart(int N, int M, int K, vi A) {
  	dbg("SMART");
  
  	// case 1: length of array divisible by N
  
  	// ll tot = 0;
  	// each(t,A) tot += t;
  	// mi ans = 0;
  	// tot %= K;
  
  
  	vi cur;
  	int tot;
  	mi ans = 0;
  	{
  		int psum = 0;
  		F0R(i,N) {
  			cur.pb(psum);
  			psum = (psum+A[i])%K;
  		}
  		tot = psum;
  		F0R(i,N) {
  			cur.pb(psum);
  			psum = (psum+A[i])%K;
  		}
  	}
  
  	{
  		int need = (tot == 0 ? 1 : K);
  		ans += mi(N)*M*((M-1)/need);
  		if (M % need == 0) ++ans;
  	}
  	if (tot == 0) {
  		vi cnt(K); F0R(i,N) ++cnt[cur[i]];
  		F0R(i,K) ans += mi(cnt[i])*(cnt[i]-1)*M*M;
  		return ans;
  	}
  	// dbg("WHOOPS",tot,K);
  
  	int ip = 1; while ((ll)ip*tot % K != 1) ++ip;
  	each(t,cur) t = (ll)t*ip%K;
  	ans += mi(M)*N*(N-1)*(M/K);
  
  	Tree<pi> T;
  	auto ins = [&](int x) {
  		T.insert({cur[x],x});
  	};
  	auto del = [&](int x) {
  		auto it = T.find({cur[x],x}); assert(it != end(T));
  		T.erase(it);
  	};
  	auto at_most = [&](int x) {
  		return T.ook({x,MOD});
  	};
  	
  	F0R(i,N) {
  		if (i == 0) {
  			FOR(j,1,N) ins(j);
  		} else {
  			ins(i+N-1);
  			del(i);
  		}
  		// auto at_most = [&](int x) {
  		// 	int ret = 0;
  		// 	FOR(j,1,N) if (cur[i+j] <= x) ++ret;
  		// };
  		mi num = at_most(cur[i])-at_most(cur[i]-M%K);
  		num += at_most(cur[i]+K)-at_most(cur[i]+K-M%K);
  		ans += M*num;
  		// F0R(k,M) {
  		// 	k = cur[i]-cur[i+j] mod K;
  		// }
  		// 0 <= cur[i]-cur[i+j] < M%k
  		// cur[i]-(M%K) < cur[i+j] <= cur[i] -> M/K+1
  		// otherwise: M/K
  	}
  	return ans;
  	// F0R(i,N) FOR(j,i+1,N) {
  	// 	F0R(k,M) if ((cur[j]-cur[i]+k*psum)%K == 0) {
  	// 		ans += M;
  	// 	}
  	// }
  	// F0R(i,N) F0R(j,i) {
  	// 	F0R(k,M) if ((cur[j]-cur[i]+(k+1)*psum)%K == 0) {
  	// 		ans += M;
  	// 	}
  	// }
  	// ps(ans);
  	// you should actually read the stuff at the bottom
  }
  
  mi dumb(int N, int M, int K, vi A) {
  	dbg("DUMB");
  	vi arr; F0R(i,N*M) arr.pb(A[i%N]);
  	int ans = 0;
  	F0R(i,N*M) {
  		rotate(begin(arr),1+all(arr));
  		int sum = 0;
  		each(t,arr) {
  			sum = (sum+t)%K;
  			ans += sum == 0;
  		}
  		if (i != 0) ans -= sum == 0;
  	}
  	return ans;
  }
  
  int main() {
  	setIO();
  	ints(N,M,K);
  	vi A(N); re(A);
  	ps(smart(N,M,K,A));
  	// ps(dumb(N,M,K,A));
  	// vi choices{1,2,3,5,7,11};
  	// rep(1000) {
  	// 	int N = rng()%10+1, M = rng()%10+1;
  	// 	int K = choices[rng()%sz(choices)];
  	// 	dbg("DOING",_,N,M);
  	// 	vi A; rep(N) A.pb(rng()%K);
  	// 	mi a = smart(N,M,K,A);
  	// 	mi b = dumb(N,M,K,A);
  	// 	if (a != b) {
  	// 		dbg("FAIL",N,M,K,A);
  	// 		exit(0);
  	// 	}
  	// }
  
  }
  
  /* stuff you should look for
  	* int overflow, array bounds
  	* special cases (n=1?)
  	* do smth instead of nothing and stay organized
  	* WRITE STUFF DOWN
  	* DON'T GET STUCK ON ONE APPROACH
  */