immutable multi = true;
immutable mod = 1000000007L;
alias Zp = Z!mod;
static this()
{
	Zp.makeFactorials(200_000+1);
}

void solve(int tc)
{
	auto n = readInt!int;
	auto k = readInt!int;
	if (k == 0)
	{
		return writeln(1);
	}
	Zp[] solveMem = new Zp[](k);
	Zp properEvenSubsets = Zp(0);
	for(int t = 0; t < n; t += 2) properEvenSubsets = properEvenSubsets + Zp.C(n, t);
	Zp solve(int d)
	{
		if (d == 0)
		{
			Zp ans = Zp(0);
			// 1 - 0
			if (n % 2 == 0) ans = ans + Zp(1);
			// 1 - 1
			if (n % 2 == 1) ans = ans + Zp(1);
			// 0 - 0
			ans = ans + properEvenSubsets;
			return ans;
		}
		Zp ans = Zp(0);
		// 1 - 0
		if (n % 2 == 0)
		{
			ans = ans + Zp(2)^^(cast(long)d * cast(long)n);
		}
		// 1 - 1
		if (n % 2 == 1)
		{
			ans = ans + solveMem[d - 1];
		}
		// 0 - 0
		ans = ans + properEvenSubsets * solveMem[d - 1];
		return ans;
	}
	foreach(d; 0 .. k) solveMem[d] = solve(d);
	solveMem[k-1].rep.writeln;
}

// main {{{
void main()
{
	auto t = multi? readInt!int : 1;
	foreach(tc; 0 .. t) solve(tc);
}
// }}}
// input {{{
int currChar;
static this()
{
	currChar = ' ';
}

char topChar()
{
	return cast(char) currChar;
}

void popChar()
{
	import core.stdc.stdio;
	currChar = getchar();
}

auto readInt(T)()
{
	T num = 0;
	int sgn = 0;
	while (topChar.isWhite)
		popChar;
	while (topChar == '-' || topChar == '+')
	{
		sgn ^= (topChar == '-');
		popChar;
	}
	while (topChar.isDigit)
	{
		num *= 10;
		num += (topChar - '0');
		popChar;
	}
	if (sgn)
		return -num;
	return num;
}

string readString()
{
	string res = "";
	while (topChar.isWhite)
		popChar;
	while (!topChar.isWhite)
	{
		res ~= topChar;
		popChar;
	}
	return res;
}
auto ra(V)()
{
	int n = readInt!int;
	return ma(n, readInt!V);
}
auto rt(V)()
{
	int n = readInt!int;
	int m = readInt!int;
	return ma(n, ma(m, readInt!V));
}
auto rbg()
{
	int n = readInt!int;
	int m = readInt!int;
	auto adj = new int[][](n);
	foreach(i; 0 .. m)
	{
		auto u = readInt!int - 1;
		auto v = readInt!int - 1;
		adj[u] ~= v;
		adj[v] ~= u;
	}
	return adj;
}
auto ma(V)(size_t n, lazy V v)
{
	auto arr = new V[](n);
	foreach(ref ai; arr) ai = v;
	return arr;
}
// }}}
// imports {{{
import std.stdio;
import std.algorithm;
import std.typecons;
import std.math;
import std.numeric;
import std.container;
import std.range;
import std.array;
import std.ascii;
// }}}
// modular {{{
struct Z(immutable long m)
{
	long rep;
	static immutable bool primeModulus = isPrime(m);
	static Z!m[] fact;
	static if (primeModulus) { static Z!m[] invFact; }
	static makeFactorials(int n)
	{
		fact = new Z!m[](n + 1);
		fact[0] = Z!m(1);
		foreach(i; 1 .. n + 1) fact[i] = Z!m(i) * fact[i - 1];
		static if (primeModulus)
		{
			invFact = new Z!m[](n + 1);
			invFact[n] = fact[n].inv;
			foreach_reverse(i; 0 .. n) invFact[i] = Z!m(i + 1) * invFact[i + 1];
		}
	}

	this(long num)
	{
		rep = num;
	}

	Z!m opBinary(string operator)(Z!m rhs)
	{
		static if (operator == "+")
		{
			long result = rhs.rep + this.rep;
			if (result >= m)
				result -= m;
			return Z!m(result);
		}
		else static if (operator == "-")
		{
			long result = this.rep - rhs.rep;
			if (result < 0)
				result += m;
			return Z!m(result);
		}
		else static if (operator == "*")
		{
			long result = this.rep * rhs.rep;
			if (result >= m)
				result %= m;
			return Z!m(result);
		}
		else static if (operator == "/" && primeModulus)
		{
			assert(rhs != Z!m(0));
			return this * rhs.inv;
		}
		else
		{
			static assert(text("Operator ", operator, " not supported"));
		}
	}

	Z!m opBinary(string operator)(long exponent) if (operator == "^^")
	{
		assert(exponent >= 0);
		Z!m base = this;
		Z!m result = 1;
		while (exponent)
		{
			if (exponent & 1)
				result = result * base;
			base = base * base;
			exponent >>= 1;
		}
		return result;
	}

	static if (primeModulus)
	{
		Z!m inv()
		{
			return this^^(m - 2);
		}
		static Z!m C(int n, int k)
		{
			if (k < 0 || k > n) return Z!m(0);
			return fact[n] * invFact[k] * invFact[n - k];
		}
	}

	invariant
	{
		assert(rep >= 0 && rep < m);
	}
}
bool isPrime(long n)
{
	for(long d = 2; d * d <= n; d++)
		if (n % d == 0) return false;
	return true;
}
unittest
{
	alias Zp = Z!23;
	static assert(Zp.primeModulus);
	foreach(i; 1 .. 23) assert(Zp(i) * Zp(i).inv == Zp(1));
	Zp.makeFactorials(22);
	foreach(i; 0 .. 23) assert(Zp.fact[i] * Zp.invFact[i] == Zp(1));
	assert(Zp.C(3, 2) == Zp(3));
	assert(Zp.C(4, 2) == Zp(6));
}
// }}}


import std.algorithm;
import std.array;
import std.container;
import std.conv;
import std.exception;
import std.functional;
import std.math;
import std.numeric;
import std.range;
import std.stdio;
import std.string;
import std.typecons;
import core.bitop;

void main ()
{
	long s;
	long x;
	while (readf (" %s %s", &s, &x) > 0)
	{
		long [2] f = [1, 0];
		long res = (s == x) ? -2 : 0;
		while (s > 0 || x > 0)
		{
			long [2] g = [0, 0];
			foreach (a; 0..2)
			{
				foreach (b; 0..2)
				{
					foreach (t; 0..2)
					{
						int xbit = a ^ b;
						int ssum = a + b + t;
						int sbit = ssum & 1;
						int cbit = ssum >> 1;
						if (sbit == (s & 1) &&
						    xbit == (x & 1))
						{
							g[cbit] += f[t];
						}
					}
				}
			}
			f[] = g[];
			s >>= 1;
			x >>= 1;
		}
		res += f[0];
		writeln (res);
	}
}


import std.stdio, std.array, std.string, std.conv, std.algorithm;
import std.typecons, std.range, std.random, std.math, std.container;
import std.numeric, std.bigint, core.bitop;

void main() {
    auto A = readln.chomp;
    auto B = readln.chomp;
    if (B.length > A.length) {
        auto C = A.to!(dchar[]);
        C.sort!"a > b";
        C.writeln;
        return;
    }

    auto N = A.length.to!int;
    auto dp = new long[][](1 << N, 2);
    foreach (i; 0..(1<<N)) dp[i].fill(-1);
    dp[0][0] = 0;

    auto masks = (1<<N).iota.array;
    masks.sort!((a,b) => a.popcnt < b.popcnt);

    foreach (mask; masks) {
        int done = mask.popcnt;
        foreach (k; 0..2) {
            if (dp[mask][k] == -1) continue;
            foreach (i; 0..N) {
                if (mask & (1<<i)) continue;
                if (k == 0 && A[i] > B[done]) continue;
                int next = mask | (1 << i);
                int under = k || (A[i] < B[done]);
                dp[next][under] = max(dp[next][under],
                                      dp[mask][k] + 10L^^(N-done-1) * (A[i]-'0'));
            }
        }
    }

    dp[(1<<N)-1].reduce!max.writeln;
}


import std.stdio, std.conv, std.string, std.array, std.range, std.algorithm, std.container;
import std.math, std.random, std.bigint, std.datetime, std.format;
void main(string[] args){ if(args.length > 1) if(args[1] == "-debug") DEBUG = 1; solve(); } bool DEBUG = 0;
void log(A ...)(lazy A a){ if(DEBUG) print(a); }
void print(){ writeln(""); } void print(T)(T t){ writeln(t); } void print(T, A ...)(T t, A a){ write(t, " "), print(a); }
string unsplit(T)(T xs){ return xs.array.to!(string[]).join(" "); }
string scan(){ static string[] ss; while(!ss.length) ss = readln.chomp.split; string res = ss[0]; ss.popFront; return res; }
T scan(T)(){ return scan.to!T; } T[] scan(T)(int n){ return n.iota.map!(i => scan!T()).array; }
T lowerTo(T)(ref T x, T y){ if(x > y) x = y; return x; } T raiseTo(T)(ref T x, T y){ if(x < y) x = y; return x; }

// ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- //

void solve(){
    long n = scan!long, m = scan!long;

    Finite pow = Finite(1);
    foreach(i; 0 .. n - 3) pow *= 2;

    Finite ans = pascal(m - n + 1, n - 1) * (n - 2) * pow;
    ans.print;
}

struct Finite{
	long value; static long mod = 998244353;
	this(long v){ value = val(v); }
	static long val(long v){ return (v + mod  - (v / mod) * mod) % mod; }
	bool opCast(T: bool)(){ return value != 0; }
	bool opEquals(Finite b){ return(value == b.value); }
	string toString(){ return value.to!string; }

	Finite opUnary(string s){ long v;
		if(s == "+") v = value;
		else if(s == "-") v = mod - value;
		else if(s == "++") v = value + 1;
		else if(s == "--") v = value + mod - 1;
		else assert(0, "Operator unary " ~ s ~ " not implemented");
		return Finite(v);
	}

	Finite opBinary(string s)(Finite b){ return opBinary!s(b.value); }
	Finite opBinary(string s)(long u){ long v;
		if(s == "+") v = value + u;
		else if(s == "-") v = value + mod - u;
		else if(s == "*") v = value * u;
		else if(s == "/") v = value * inv(u);
		else assert(0, "Operator " ~ s ~ " not implemented");
		return Finite(v);
	}
	Finite opBinaryRight(string s)(long u){ long v;
		if(s == "+") v = u + value;
		else if(s == "-") v = u + mod - value;
		else if(s == "*") v = u * value;
		else if(s == "/") v = u * invvalue;
		else assert(0, "Operator " ~ s ~ " not implemented");
		return Finite(v);
	}
	Finite opAssign(long v){ value = v; return this; }

	Finite opOpAssign(string s)(Finite b){ return opOpAssign!s(b.value); }
	Finite opOpAssign(string s)(long v){
		if(s == "+") value = (value + v) % mod;
		else if(s == "-") value = (value + mod - v) % mod;
		else if(s == "*") value = (value * v) % mod;
		else if(s == "/") value = (value * inv(v)) % mod;
		else assert(0, "Operator " ~ s ~ "= not implemented");
		return this;
	}

	private static long[] _inv = [0, 1];
	long invvalue(){ return inv(value); }
	long inv(long v){ int i = val(v).to!int;
		while(i >= _inv.length){
			_inv ~= _inv[(mod % $).to!int] * (mod - mod / _inv.length) % mod;
		}
		return _inv[i];
	}

}

// ---以下はユーティリティ--- //

/// mod p における階乗
/// 例 perm(6) = Finite(120)
/// オーダーはプログラム全体で出てくる最大の引数Nに対してO(N)
Finite perm(long x){ int i = Finite.val(x).to!int;
	static Finite[] _perm = [];
	if(_perm.length == 0) _perm ~= Finite(1);
	while(i >= _perm.length) _perm ~= _perm[$ - 1] * _perm.length;
	return _perm[i];
}

/// mod p における階乗の逆元
/// 例 invperm(6) = Finite(1) / Finite(120)
/// オーダーはプログラム全体で出てくる最大の引数Nに対してO(N)
/// ※ invperm(x) と inv(perm(x)) は同じ値だが、後者は計算量が O(mod) になる
Finite invperm(long x){ int i = Finite.val(x).to!int;
	static Finite[] _iperm = [];
	if(_iperm.length == 0) _iperm ~= Finite(1);
	while(i >= _iperm.length) _iperm ~= _iperm[$ - 1] / _iperm.length;
	return _iperm[i];
}

/// mod p における二項係数（定義に注意：(a + b)! / a! / b! ）
/// 例 pascal(3, 2) = Finite(10)
/// ただし、「a < 0 または b < 0」のとき答えは 0 を返します。
Finite pascal(long a, long b){
	if(a < 0 || b < 0) return Finite(0);
	return perm(a + b) * invperm(a) * invperm(b);
}


import std.stdio;

int main()
{
	int a=0;
	readf(" %d", &a);
	int o=a%4;
	if (o==0)
	{
		writeln(1);
		writeln('A');
	}
	else if (o==1)
	{
		writeln(0);
		writeln('A');
	}
	else if (o==2)
	{
		writeln(1);
		writeln('B');
	}
	else
	{
		writeln(2);
		writeln('A');
	}
	return 0;
}


import std.stdio, std.string, std.conv, std.algorithm;

void main(){

  int n; rd(n);
  auto s=readln.chomp.to!(char[]);

  if(n==1){
    writeln("Yes");
    return;
  }

  bool[char] set;
  foreach(c; s){
    if(c in set){
      writeln("Yes");
      return;
    }
    set[c]=true;
  }

  writeln("No");

}

void rd(T...)(ref T x){
  import std.stdio, std.string, std.conv;
  auto l=readln.split;
  assert(l.length==x.length);
  foreach(i, ref e; x) e=l[i].to!(typeof(e));
}


module _template;
import std.stdio;
import std.string;
import std.algorithm;
import std.container;
import std.range;
import std.math;
import std.numeric;
import std.conv;
import std.typecons;
import std.format;

struct IO {
        string[] tk;
        string readString() {
                while (tk.empty)
                        tk = readln.split;
                auto tkt = tk.front;
                tk.popFront;
                return tkt;
        }
        int readInt() {
                return readString.to!int;
        }
        double readDouble() {
                return readString.to!double;
        }
}

void main() {
        IO cin;
        int t = 1;
        // t = cin.readInt;
        while (t--) {
                int n = cin.readInt;
                int x = cin.readInt;
                int y = cin.readInt;
                writeln(ceil(y / 100.0 * n) > x ? ceil(y / 100.0 * n) - x : 0);
        }
}


import std.stdio;
import std.uni;
import std.string;
import core.stdc.stdio;
import std.array;
import std.algorithm;
import std.string;

int main(string[] argv)
{
	string line = readln();
	if (line[line.length - 1] == '\n') line.length--;
	int h = line.indexOf('h');
	int e = line.indexOf('e', (h != -1 ? h+1 : 0));
	int l = line.indexOf('l', (e != -1 ? e+1 : 0));
	int sl = line.indexOf('l', (l != -1 ? l+1 : 0));
	int o = line.indexOf('o', (sl != -1 ? sl+1 : 0));
	if (h != -1 && e != -1 && l != -1 && sl != -1 && o != -1
	 && e > h && l > e && sl > l && o > sl)
	{
		printf("YES");
	} else {
		printf("NO");
	}
	return 0;
}


import std.stdio;
import std.algorithm.comparison;
import std.algorithm.sorting;
import std.range;
import std.range.primitives;
import std.conv;

void advance(ref int i) {
    ++i;
    if (i == 4) i = 0;
}
void retreat(ref int i) {
    --i;
    if (i == -1) i = 3;
}

int main() {
    debug stdin = File("in.txt", "r");

    char[4] brd1, brd2;
    readf("%s%s\n", &brd1[0], &brd1[1]);
    readf("%s%s\n", &brd1[3], &brd1[2]);
    readf("%s%s\n", &brd2[0], &brd2[1]);
    readf("%s%s\n", &brd2[3], &brd2[2]);

    string s2 = to!string(brd2);
    int il, ir;
    if (brd1[0] == 'X') il = 0;
    else if (brd1[1] == 'X') il = 1;
    else if (brd1[2] == 'X') il = 2;
    else if (brd1[3] == 'X') il = 3;
    ir = il;
    advance(ir);
    foreach ( i; 0 .. 12 ) {
        string s1 = to!string(brd1);
        if (s1 == s2) {
            writeln("YES");
            return 0;
        }
        char tmp;
        tmp = brd1[ir];
        brd1[ir] = brd1[il];
        brd1[il] = tmp;
        advance(il);
        advance(ir);
    }
    retreat(il); retreat(ir);
    foreach ( i; 0 .. 12 ) {
        string s1 = to!string(brd1);
        if (s1 == s2) {
            writeln("YES");
            return 0;
        }
        char tmp;
        tmp = brd1[il];
        brd1[il] = brd1[ir];
        brd1[ir] = tmp;
        retreat(il);
        retreat(ir);
    }
    writeln("NO");

    return 0;
}


import std.stdio, std.string, std.conv, std.algorithm, std.numeric;
import std.range, std.array, std.math, std.typecons, std.container, core.bitop;

void main() {
    long n, k;
    scan(n, k);

    long a = 1L;
    while (a <= n) {
        a *= 2;
    }

    long ans;

    if (k == 1) ans = n;
    else ans = a - 1;
    writeln(ans);
}

void scan(T...)(ref T args) {
    string[] line = readln.split;
    foreach (ref arg; args) {
        arg = line.front.to!(typeof(arg));
        line.popFront();
    }
    assert(line.empty);
}

void fillAll(R, T)(ref R arr, T value) {
    static if (is(typeof(arr[] = value))) {
        arr[] = value;
    }
    else {
        foreach (ref e; arr) {
            fillAll(e, value);
        }
    }
}


import std.stdio;
import core.stdc.stdio;
import std.string;
import std.regex;
import std.math;
import std.algorithm;

int main(string[] argv)
{
	int n;
	scanf("%d", &n);
	int bits = 0;
	while (n > 0)
	{
		bits += (n % 2);
		n = n >> 1;
	}
	printf("%d", bits);
	return 0;
}


import std.stdio;

void main ()
{
	int n;
	while (readf (" %s", &n) > 0)
	{
		writeln (n * 1L * (n + 1) * 3 + 1);
	}
}


import std.stdio;
import std.uni;
import std.string;
import core.stdc.stdio;
import std.array;
import std.algorithm;
import std.string;
import std.math;

int gcd (int a, int b)
{
	if (b > a)
	{
		int t = a;
		a = b;
		b = t;
	}
	int r = 1;
	while (r > 0)
	{
		r = a % b;
		a = b;
		b = r;
	}
	return a;
}

int main(string[] argv)
{
	int a, b, n;
	scanf("%d %d %d", &a, &b, &n);
	int w = -1;
	while (n > 0)
	{
		++w; w %= 2;
		int g = gcd(w == 0 ? a : b, n);
		n -= g;
	}
	printf("%d", w);
	return 0;
}


import std.algorithm;
import std.range;
import std.stdio;
import std.typecons;
import std.traits;
import std.array;
struct ModularClass(T)
{
  alias pmod = positiveModularRepresentative;
  T representative, modulus;
  this(T representative, T modulus)
  {
    this.representative = pmod(representative, modulus);
    this.modulus = modulus;
  }
  T minimalPositiveRepresentative()
  {
    return ((representative % modulus) + modulus) % modulus;
  }
  T minimalNegativeRepresentative()
  {
    return ((representative % modulus) - modulus) % modulus;
  }
  T maxRepresentative(T upperBound)
  {
    return upperBound - pmod(upperBound - representative, modulus);
  }
  alias eqLowerBound = maxRepresentative;
  T minRepresentative(T lowerBound)
  {
    return lowerBound + pmod(representative - lowerBound, modulus);
  }
  alias eqUpperBound = minRepresentative;
  static ModularClass!T multiplesOf(T modulus)
  {
    return ModularClass!T(0, modulus);
  }
  ModularClass!T opBinary(string operation)(ModularClass!T other) if (operation == "+" || operation == "-" || operation == "*")
  {
    assert(other.modulus == this.modulus, "Trying to operate on modular classes of diferent modulus.");
    return ModularClass!T(mixin(q{this.representative}, operation, q{other.representative}), this.modulus);
  }
  ModularClass!T opBinary(string operation)(long n) if (operation == "^")
  {
    if(n == 0)
      {
	return ModularClass!T(1, this.modulus);
      }
    if(n & 1)
      {
	auto res = this^(n - 1);
	return this * res;
      }
    else
      {
	auto res = this^(n >> 1);
	return res * res;
      }
  }
}
struct StaticModularClass(T, T modulus)
{
  alias pmod = positiveModularRepresentative;
  T representative;
  this(T representative)
  {
    this.representative = pmod(representative, modulus);
  }
  T minimalPositiveRepresentative()
  {
    return ((representative % modulus) + modulus) % modulus;
  }
  T minimalNegativeRepresentative()
  {
    return ((representative % modulus) - modulus) % modulus;
  }
  T maxRepresentative(T upperBound)
  {
    return upperBound - pmod(upperBound - representative, modulus);
  }
  alias eqLowerBound = maxRepresentative;
  T minRepresentative(T lowerBound)
  {
    return lowerBound + pmod(representative - lowerBound, modulus);
  }
  bool opEquals(StaticModularClass!(T, modulus) other)
  {
    return modulus.divides(other.representative - representative);
  }
  alias eqUpperBound = minRepresentative;
  StaticModularClass!(T, modulus) opBinary(string operation)(StaticModularClass!(T, modulus) other)
  {
    static if(operation == "+" || operation == "-" || operation == "*")
      return StaticModularClass!(T, modulus)(mixin(q{this.representative}, operation, q{other.representative}));
    else
      static assert(false);
  }
  StaticModularClass!(T, modulus) opBinary(string operation)(long n) if (operation == "^")
  {
    if(n == 0)
      return StaticModularClass!(T, modulus)(1);
    if(n & 1)
      {
	auto partialResult = this^(n - 1);
	return this * partialResult;
      }
    else
      {
	auto partialResult = this^(n >> 1);
	return partialResult * partialResult;
      }
  }
}
// minimum positive representative of x modulo m.
T positiveModularRepresentative(T)(T x, T m)
{
  return (x % m + m) % m;
}
// solves ax + by = gcd(a, b) and returns gcd(a, b)
T extendedEuclideanAlgorithm(T)(T a, T b, out T x, out T y)
{
  alias egcd = extendedEuclideanAlgorithm;
  if (a == 0)
    {
      x = 0, y = 1;
      return b;
    }
  T x1, y1;
  auto d = egcd(b % a, a, x1, y1);
  x = y1 - (b / a) * x1, y = x1;
  return d;
}
// solves ax = b (mod m) giving a solution as a modulus class.
bool solveLinearCongruence(T)(T a, T b, T m, out ModularClass!T res)
{
  alias egcd = extendedEuclideanAlgorithm;
  alias pmod = positiveModularRepresentative;
  T x, p;
  b = b.pmod(m);
  T y;
  T g = egcd(a, m, x, y);
  if (b % g != 0)
    return false;
  p = m / g;
  x = pmod(x * b / g, p);
  res.representative = x;
  res.modulus = p;
  return true;
}
bool divides(T)(T a, T b)
{
  return b % a == 0;
}
struct Input
{
  T next(T)()
  {
    import std.conv;
    return to!T(nextWord);
  }
  string nextWord()
  {
    if (_nextWords.empty)
	_nextWords.insertFront(readln().split);
    string word = _nextWords.front; _nextWords.removeFront;
    return word;
  }
  import std.container;
  DList!string _nextWords;
}
Input input;
void read(T...)(ref T args)
{
  import std.traits;
  static foreach(i; 0 .. T.length)
    static if(isArray!(T[i]) && !is(T[i] == string))
      foreach(ref e; args[i])
    	read(e);
    else static if(isTuple!(T[i]))
      static foreach(n; 0 .. T[i].Types.length)
	read(args[i][n]);
    else
      args[i] = input.next!(typeof(args[i]))();
}
auto itup(alias k, alias F)()
{
  alias T = Parameters!F;
  foreach(i; 0 .. k)
    {
      T t; get(t);
      F(t);
    }
}
alias get = read;
void wone(T)(T t, char end)
{
  static if(isArray!T && !is(T == string))
    {
      foreach(i; 0 .. t.length - 1)
	  write(t[i], ' ');
      write(t[$ - 1], end);
    }
  else
      write(t, end);
}
void wr(T...)(T t)
{
  static foreach(i; 0 .. T.length)
    static if(i + 1 < T.length)
      wone(t[i], ' ');
    else
      wone(t[i], '\n');
}
void ans(T...)(T t)
{
  import core.stdc.stdlib;
  wr(t);
  exit(0);
}

auto primeDivisors(T)(T x)
{
  T[] res;
  for(T candidate = 2; candidate * candidate <= x; candidate++)
    {
      if (x % candidate == 0)
	res ~= candidate;
      while (x % candidate == 0)
	  x /= candidate;
    }
  if (x > 1)
    res ~= x;
  return res;
}
immutable p = 1_000_000_000 + 7;
alias mod = StaticModularClass!(long, p);
auto maxDivideFact(T)(T prime, T n)
{
  T pot = 0;
  while(n)
    {
      pot += n / prime;
      n /= prime;
    }
  mod res = prime;
  return (res ^ pot);
}

struct Test
{
  int x, y;
}

int[1000] s = -2;

void main()
{
  long x, n; get(x, n);
  wr(x.primeDivisors.fold!((acc, prime) => acc * maxDivideFact(prime, n))(mod(1)).representative);
}