#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <string.h>
#include <fstream>
#include <cassert>
using namespace std;


typedef long long ll;
const int M = 1e6;
const ll mod = 1e9 + 7;

ll cr[M], cl[M], c[M];

struct node {/*{{{*/
public:
  ll m, ml, mr, mm;
  int li, ri;
  void merge(node& l, node& r) {
    li = l.li;
    ri = r.ri;
    ll s = (cr[l.ri] * cl[r.li]) % mod;
    m = (l.m*r.m) % mod;
    m = (m + ((l.ml*r.mr) % mod)*s) % mod;
    ml = (l.m*r.ml) % mod;
    ml = (ml + ((l.ml*r.mm) % mod)*s) % mod;
    mr = (r.m*l.mr) % mod;
    mr = (mr + ((r.mr*l.mm) % mod)*s) % mod;
    mm = (l.mr*r.ml) % mod;
    mm = (mm + ((l.mm*r.mm) % mod)*s) % mod;
  }
  node() {
    li = 0, ri = 0, ml = 1, mr = 1, mm = 0, m = 1;
  }
  void init() {
    li = 0, ri = 0, ml = 1, mr = 1, mm = 0, m = 1;
  }
};/*}}}*/
template<class node>
class segtree {/*{{{*/
  template<bool b>class param {};
  inline void spltdwn(int idx, param<true>) { splt(idx); }
  inline void splt(int idx) {/*{{{*/
    idx >>= 1;
    if (idx>0)splt(idx);
    tree[idx].split(tree[idx << 1], tree[(idx << 1) | 1]);
  }/*}}}*/
  inline void spltdwn(int, param<false>) {};
  inline void split(node& a, node& b, node& c, param<true>) { return a.split(b, c); }
  inline void split(node&, node&, node&, param<false>) {}
  template<typename t, void (t::*)(t&, t&)> class T {};
  template<typename t> static char test(T<t, &t::split>*) { return 0; }
  template<typename t> static long double test(...) { return 0; }
  int u, v;
  node query(int root, int left_range, int right_range) {/*{{{*/
    if (u <= left_range && right_range <= v)
      return tree[root];
    int mid = (left_range + right_range) >> 1,
      l = root << 1,
      r = l | 1;
    if (has_split)split(tree[root], tree[l], tree[r], param<has_split>());
    node res;
    if (u >= mid)res = query(r, mid, right_range);
    else if (v <= mid)res = query(l, left_range, mid);
    else {
      node n1 = query(l, left_range, mid),
        n2 = query(r, mid, right_range);
      res.merge(n1, n2);
    }
    if (has_split) tree[root].merge(tree[l], tree[r]);
    return res;
  }/*}}}*/
  template<void(*fn)(node&)>
  void local_update(int root, int left_range, int right_range) {/*{{{*/
    if (u <= left_range && right_range <= v) {
      return fn(tree[root]);
    }
    int mid = (left_range + right_range) >> 1,
      l = root << 1,
      r = l | 1;
    if (has_split)split(tree[root], tree[l], tree[r], param<has_split>());
    if (v>mid)local_update<fn>(r, mid, right_range);
    if (u<mid)local_update<fn>(l, left_range, mid);
    tree[root].merge(tree[l], tree[r]);
  }/*}}}*/
  void mrgup(int idx) {/*{{{*/
    idx >>= 1;
    while (idx>0)
      tree[idx].merge(tree[idx << 1], tree[(idx << 1) | 1]),
      idx >>= 1;
  }/*}}}*/
public:
  static bool const has_split = (sizeof(test<node>(0)) == sizeof(char));
  int N;
  int leftmost_leaf, rightmost_leaf;
  node* tree;
  node identity;
  segtree() { tree = 0; }
  ~segtree() {
    if (tree) delete[] tree;
  }
  void init(int n, const node a[], const node& identity) {/*{{{*/
    if (tree) delete[] tree;
    this->identity = identity;
    N = 0;
    while ((1 << N)<n)N++;
    leftmost_leaf = 1 << N;
    rightmost_leaf = leftmost_leaf << 1;
    tree = new node[rightmost_leaf];
    for (int i = 0; i<n; i++)
      tree[i + leftmost_leaf] = a[i];
    for (int i = n + leftmost_leaf; i<rightmost_leaf; i++)
      tree[i] = identity;
    for (int i = leftmost_leaf - 1; i; i--)
      tree[i].merge(tree[i << 1], tree[(i << 1) | 1]);
  }/*}}}*/
  node query(int u, int v) {//[u,v]/*{{{*/
    this->u = u + leftmost_leaf;
    this->v = v + leftmost_leaf + 1;
    return query(1, leftmost_leaf, rightmost_leaf);
  }/*}}}*/
  node query(int u) {//faster version of query(u,u)/*{{{*/
                     //indexing starts from 0
    u += leftmost_leaf;
    spltdwn(u, param<has_split>());
    return tree[u];
  }/*}}}*/
  template<void(*fn)(node&)>
  void update(int u, int v) {/*{{{*/
                             //0-indexed
    this->u = u + leftmost_leaf;
    this->v = v + leftmost_leaf + 1;
    return local_update<fn>(1, leftmost_leaf, rightmost_leaf);
  }/*}}}*/
  template<void(*fn)(node&)>
  void update(int u) {//faster version of update(u,u)/*{{{*/
                      //indexing starts from 0
    u += leftmost_leaf;
    spltdwn(u, param<has_split>());
    fn(tree[u]);
    mrgup(u);
  }/*}}}*/
  void split_down(int leaf_idx) {/*{{{*/
    spltdwn(leaf_idx + leftmost_leaf, param<has_split>());
  }/*}}}*/
  void merge_up(int leaf_idx) {/*{{{*/
    mrgup(leaf_idx + leftmost_leaf);
  }/*}}}*/
  bool is_leaf(int tree_idx) { return tree_idx >= leftmost_leaf; }
  int binary_search(node k) {/*{{{*/
                             //search the last place i, such that merge( everyting to the left of i(including i) ) compares less than k
    int root = 1;
    node n = identity;
    //identity satisfies merge(identity,y) = merge(y,identity) = y for all y.
    assert(!(k<identity));
    while (!is_leaf(root)) {
      int left_child = root << 1,
        right_child = left_child | 1;
      if (has_split)
        split(tree[root], tree[left_child], tree[right_child], param<has_split>());
      node m;
      m.merge(n, tree[left_child]);
      if (m<k) {//go to right side
        n = m;
        root = right_child;
      }
      else root = left_child;
    }
    node m;
    m.merge(n, tree[root]);
    mrgup(root);
    if (m<k)return root - leftmost_leaf;
    else return root - 1 - leftmost_leaf;
  }/*}}}*/
};/*}}}*/

#define boost ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define sz(a) int((a).size())
#define rep(i, s, n)  for(int i = s; i <= (n); ++i)
#define rev(i, n, s)  for(int i = (n); i >= s; --i)
#define fore(x, a) for(auto &&x : a)
const ll inf = mod-7;

ll w[M];
ll d[M], zo[M], s[M];

node a[M];

void upd(node &cur) {
  cur.m = c[cur.li];
}

int main() {
#ifdef loc
  if(!freopen((string(FOLDER) + "inp.txt").c_str(), "r", stdin)) {
    assert(0);
  }
  freopen((string(FOLDER) + "out.txt").c_str(), "w", stdout);
#endif
  boost;
  int t;
  cin >> t;
  rep(z, 1, t) {
    cout << "Case #" << z << ": ";
    int n, m;
    cin >> n >> m;
    ll w1, aw, bw;
    cin >> w1 >> aw >> bw;
    w[1] = w1;
    rep(i,2, m) {
      w[i] = ((aw*w[i - 1] + bw) % n) + 1;
    }
    ll d1, ad, bd;
    cin >> d1 >> ad >> bd;
    d[1] = d1;
    rep(i, 2, m) {
      d[i] = (ad*d[i - 1] + bd) % 3;
    }
    rep(i, 1, m) {
      zo[i] = max(1LL, min((ll)n, w[i] + d[i] - 1));
    }
    ll s1, as, bs;
    cin >> s1 >> as >> bs;
    s[1] = s1;
    rep(i, 2, m) {
      s[i] = ((as*s[i - 1] + bs) % inf) + 1;
    }
    rep(i, 0,n+1) {
      a[i].init();
      a[i].li = i;
      a[i].ri = i;
    }
    memset(cl, 0, sizeof(cl));
    memset(cr, 0, sizeof(cr));
    memset(c, 0, sizeof(c));
    rep(i, 1, n) c[i] = 1;
    segtree<node> p;
    p.init(n + 1, a, a[n + 1]);
    int res = 0;
   // cout << p.query(1, n).m << " ";
    rep(i, 1, m) {
      //cout << "(" << w[i] << " " << zo[i] << " " << s[i] << ") ";
      if (w[i] == zo[i]) {
        c[w[i]] += s[i];
        if (c[w[i]] >= mod) c[w[i]] -= mod;
      }
      else if (w[i] == zo[i] - 1) {
        cr[w[i]] += s[i];
        if (cr[w[i]] >= mod) cr[w[i]] -= mod;
      }
      else {
        cl[w[i]] += s[i];
        if (cl[w[i]] >= mod) cl[w[i]] -= mod;
      }
      p.update<&upd>(w[i]);
      res += p.query(1, n).m;
    //  cout << p.query(1, n).m << " ";
      if (res >= mod) res -= mod;
    }
    cout << res << endl;
  }
  return 0;
}