using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;

namespace ReadWriteTemplate
{
    public static class Solver
    {
        private static void SolveCase()
        {
            long m = ReadLong();
            long a = ReadLong();
            long b = ReadLong();

            long[] f = Enumerable.Repeat(-1L, (int)a).ToArray();
            f[0] = 0;
            long[] l = new long[a];

            var queue = new Queue<long>();
            queue.Enqueue(0);
            while (queue.Count > 0)
            {
                long cur = queue.Dequeue();
                long d = cur + (b - cur + a - 1) / a * a;
                long t = d - b;
                while (t >= 0 && f[t % a] < 0)
                {
                    f[t % a] = Math.Max(d, f[cur % a]);
                    l[t % a] = t;
                    // Writer.WriteLine($"{t % a} - {f[t % a]} {l[t % a]}");
                    queue.Enqueue(t);
                    t -= b;
                }
            }

            // WriteArray(f);

            long ans = 0;
            for (int i = 0; i < a; i++)
            {
                if (f[i] >= 0 && f[i] <= m)
                {
                    long k = Calc(m, l[i], a) - Calc(f[i] - 1, l[i], a);
                    // Writer.WriteLine($"{i} : {k}");
                    ans += k;
                }
            }

            Writer.WriteLine(ans);
        }

        public static long Calc(long st, long k, long a)
        {
            long full = (st - k + 1) / a;
            long ans = a * full * (full + 1) / 2;
            ans += (st - k + 1) % a * (full + 1);
            return ans;
        }

        public static long Gcd(long a, long b)
        {
            return b == 0 ? a : Gcd(b, a % b);
        }

        public static void Solve()
        {
#if DEBUG
            var sw = Stopwatch.StartNew();
#endif

            SolveCase();

            /*int T = ReadInt();
            for (int i = 0; i < T; i++)
            {
                // Writer.Write("Case #{0}: ", 1 - t);
                SolveCase();
            }*/

#if DEBUG
            sw.Stop();
            Console.WriteLine($"{sw.ElapsedMilliseconds} ms");
#endif
        }

        public static void Main()
        {
            Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

#if DEBUG
            // Reader = Console.In; Writer = Console.Out;
            Reader = File.OpenText("input.txt"); Writer = File.CreateText("output.txt");
#else
            Reader = Console.In; Writer = Console.Out;
#endif

            // Solve();
            Thread thread = new Thread(Solve, 64 * 1024 * 1024);
            thread.CurrentCulture = CultureInfo.InvariantCulture;
            thread.Start();
            thread.Join();

            Reader.Close();
            Writer.Close();
        }

        public static IOrderedEnumerable<TSource> OrderByWithShuffle<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
        {
            return source.Shuffle().OrderBy(keySelector);
        }

        public static T[] Shuffle<T>(this IEnumerable<T> source)
        {
            T[] result = source.ToArray();
            Shuffle(result);
            return result;
        }

        private static void Shuffle<T>(IList<T> array)
        {
            Random rnd = new Random();
            for (int i = array.Count - 1; i >= 1; i--)
            {
                int k = rnd.Next(i + 1);
                T tmp = array[k];
                array[k] = array[i];
                array[i] = tmp;
            }
        }

        #region Read/Write

        private static TextReader Reader;

        private static TextWriter Writer;

        private static Queue<string> CurrentLineTokens = new Queue<string>();

        private static string[] ReadAndSplitLine()
        {
            return Reader.ReadLine().Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
        }

        public static string ReadToken()
        {
            while (CurrentLineTokens.Count == 0)
                CurrentLineTokens = new Queue<string>(ReadAndSplitLine());
            return CurrentLineTokens.Dequeue();
        }

        public static string ReadLine()
        {
            return Reader.ReadLine();
        }

        public static int ReadInt()
        {
            return int.Parse(ReadToken());
        }

        public static long ReadLong()
        {
            return long.Parse(ReadToken());
        }

        public static double ReadDouble()
        {
            return double.Parse(ReadToken(), CultureInfo.InvariantCulture);
        }

        public static int[] ReadIntArray()
        {
            return ReadAndSplitLine().Select(int.Parse).ToArray();
        }

        public static long[] ReadLongArray()
        {
            return ReadAndSplitLine().Select(long.Parse).ToArray();
        }

        public static double[] ReadDoubleArray()
        {
            return ReadAndSplitLine().Select(s => double.Parse(s, CultureInfo.InvariantCulture)).ToArray();
        }

        public static int[][] ReadIntMatrix(int numberOfRows)
        {
            int[][] matrix = new int[numberOfRows][];
            for (int i = 0; i < numberOfRows; i++)
                matrix[i] = ReadIntArray();
            return matrix;
        }

        public static string[] ReadLines(int quantity)
        {
            string[] lines = new string[quantity];
            for (int i = 0; i < quantity; i++)
                lines[i] = Reader.ReadLine().Trim();
            return lines;
        }

        public static void WriteArray<T>(IEnumerable<T> array)
        {
            Writer.WriteLine(string.Join(" ", array));
        }

        #endregion
    }
}


using System;
using System.Collections.Generic;
using System.Text;

namespace CodeForces
{
    class Program
    {
        static void Main(string[] args)
        {
            int m = int.Parse(Console.ReadLine());
            int[,] matrix = new int[5, 5];
            for (int i = 0; i < m; i++)
            {
                string[] s = Console.ReadLine().Split(' ');
                int k1 = int.Parse(s[0]);
                int k2 = int.Parse(s[1]);
                matrix[k1 - 1, k2 - 1] = 1;
                matrix[k2 - 1, k1 - 1] = 1;
            }
            for (int i = 0; i < 5; i++)
            {
                for (int j = 0; j < 5; j++)
                {
                    if (matrix[i, j] == 1)
                    {
                        for (int k = 0; k < 5; k++)
                        {
                            if ((k != i) & (k != j) & (i != j) & (matrix[i, k] == 1) & (matrix[j, k] == 1))
                            {
                                Console.Write("WIN"); return; }
                        }
                    }
                    else
                    {
                        for (int k = 0; k < 5; k++)
                        {
                            if ((k != i) & (k != j) & (i!=j) & (matrix[i, k] == 0) & (matrix[j, k] == 0)) {
                                Console.Write("WIN"); return; }
                        }
                    }
                }
            }
            Console.Write("FAIL");
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Friends
{
    class Program
    {
        static void Main(string[] args)
        {
            int m = int.Parse(Console.ReadLine());

            int[] aux = new int[6];

            for(int i = 0 ; i < m ; ++i )
            {
                string[] ab = Console.ReadLine().Split(' ');
                int a = int.Parse(ab[0]);
                int b = int.Parse(ab[1]);

                aux[a]++;
                aux[b]++;
            }

            bool f = false;

            for(int i = 1 ; i < 6 ; ++i )
            {
                if(aux[i] >= 3 || aux[i] <= 1)
                {
                        f = true;
                        break;
                }
            }

            if(f)
            {
                Console.WriteLine("WIN");
            }
            else
            {
                Console.WriteLine("FAIL");
            }
        }
    }
}


using System;

namespace Task2 {
    internal class Program {
        private static int[][] _mat = new int[5][];

        private static void Main(string[] args) {
            int m = int.Parse(Console.ReadLine());
            _mat = new int[5][];
            for (int i = 0; i < 5; i++) {
                _mat[i] = new int[5];
            }
            for (int i = 0; i < m; i++) {
                string s = Console.ReadLine();
                string[] ss = s.Split(' ');
                int a = int.Parse(ss[0]) - 1;
                int b = int.Parse(ss[1]) - 1;
                _mat[a][b] = 1;
                _mat[b][a] = 1;
            }
            for (int a = 0; a < 5; a++) {
                for (int b = a + 1; b < 5; b++) {
                    for (int c = b + 1; c < 5; c++) {
                        if (First(a, b, c)) {
                            Console.WriteLine("WIN");
                            return;
                        }
                        if (Second(a, b, c)) {
                            Console.WriteLine("WIN");
                            return;
                        }
                    }
                }
            }
            Console.WriteLine("FAIL");
        }

        private static bool Second(int a, int b, int c) {
            if (_mat[a][b] == 0 && _mat[b][c] == 0 && _mat[c][a] == 0)
                return true;
            return false;
        }

        private static bool First(int a, int b, int c) {
            if (_mat[a][b] > 0 && _mat[b][c] > 0 && _mat[c][a] > 0)
                return true;
            return false;
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace b1cs
{
    class Program
    {
        static void Main(string[] args)
        {
            bool[,] z = new bool[5, 5];
            int n = int.Parse(Console.ReadLine());
            for (int i = 0; i < n; i++)
            {
                string[] ss = Console.ReadLine().Split();
                int a = int.Parse(ss[0]);
                int b = int.Parse(ss[1]);
                a--;b--;
                z[a, b] = true;
                z[b, a] = true;
            }
            for (int a = 0; a < 3; a++)
            {
                for (int b = a + 1; b < 4; b++)
                {
                    for (int c = b + 1; c < 5; c++)
                    {
                        if ((z[a, b] && z[a, c] && z[b, c]) || (!z[a, b] && !z[a, c] && !z[b, c]))
                        {
                            Console.WriteLine("WIN");
                            return;
                        }
                    }
                }
            }
            Console.WriteLine("FAIL");
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
           try
            {
                int m = int.Parse(Console.ReadLine());
                int[] ar = new int[6];
                for (int i = 0; i < m; i++)
                {
                    int[] ar2 = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();
                    ar[ar2[0]-1]++;
                    ar[ar2[1]-1]++;
                }
                int c = 0;
                if (m % 2 == 0)
                    c = m / 2;
                else
                    c = m / 2 + 1;
                bool q = false;
                for (int i = 0; i < 5; i++)
                {
                    if(ar[i]>=c || ar[i]>=3)
                    {
                        q = true;
                        break;
                    }
                }
                if(q)
                    Console.WriteLine("WIN");
                else
                    Console.WriteLine("FAIL");
                Console.ReadKey();
           }
          catch { }
        }

    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {

        static void Main(string[] args)
        {
            int N = Convert.ToInt16(Console.ReadLine());
            Boolean[,] friends = new Boolean[6, 6];
            for (int i = 0; i < N; ++i)
            {
                String S = Console.ReadLine();
                String[] A = S.Split(' ');
                int a = Convert.ToInt16(A[0]);
                int b = Convert.ToInt16(A[1]);
                friends[a, b] = true;
                friends[b, a] = true;
            }
            for(int i = 1; i <= 3; ++ i)
            {
                for (int j = i + 1; j <= 4; ++j)
                {
                    for (int k = j + 1; k <= 5; ++k)
                    {
                        if ((friends[i, j] == true && friends[j, k] == true&& friends[k, i])==true || (friends[i, j]==false && friends[j, k]==false && friends[k, i] ==false))
                        {
                            Console.WriteLine("WIN");
                            return;
                        }
                    }
                }
            }
            Console.WriteLine("FAIL");
        }

    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace prog2
{
    class Program
    {
        static void Main(string[] args)
        {
            int n = Convert.ToInt32(Console.ReadLine());
            bool[,] map = new bool[5,5];
            for (int i = 0; i < n;i++ )
            {
                string[] ss = Console.ReadLine().Split(' ');
                map[Convert.ToInt32(ss[0])-1, Convert.ToInt32(ss[1])-1] = true;
                map[Convert.ToInt32(ss[1])-1, Convert.ToInt32(ss[0])-1] = true;
            }
            bool flag = false;
            for (int i = 0; i < 5;i++ )
            {
                for (int j=0;j<4;j++)
                    if (map[i,j])
                    {
                        for(int q=j+1;q<5;q++)
                            if ((map[i,q]) && (map[q,j]))
                            {
                                flag = true;
                                break;
                            }
                        if (flag) break;
                    }
                if (flag) break;
            }
            if (!flag)
            {
                map[0, 0] = true;
                map[1, 1] = true;
                map[2, 2] = true;
                map[3, 3] = true;
                map[4, 4] = true;
                for (int i = 0; i < 5; i++)
                {
                    for (int j = 0; j < 4; j++)
                        if (!map[i, j])
                        {
                            for (int q = j + 1; q < 5; q++)
                                if ((!map[i, q]) && (!map[q, j]))
                                {
                                    flag = true;
                                    break;
                                }
                            if (flag) break;
                        }
                    if (flag) break;
                }
            }
            if (flag) Console.WriteLine("WIN"); else Console.WriteLine("FAIL");
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
           try
            {
                int m = int.Parse(Console.ReadLine());
                int[] ar = new int[6];
                for (int i = 0; i < m; i++)
                {
                    int[] ar2 = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();
                    ar[ar2[0]-1]++;
                    ar[ar2[1]-1]++;
                }
                int c = 0;
                if (m % 2 == 0)
                    c = m / 2;
                else
                    c = m / 2 + 1;
                bool q = false;
                for (int i = 0; i < 5; i++)
                {
                    if(ar[i]>=c)
                    {
                        q = true;
                        break;
                    }
                }
                if(q)
                    Console.WriteLine("WIN");
                else
                    Console.WriteLine("FAIL");
                Console.ReadKey();
           }
          catch { }
        }

    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
           try
            {
                int m = int.Parse(Console.ReadLine());
                int[] ar = new int[6];
                for (int i = 0; i < m; i++)
                {
                    int[] ar2 = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();
                    ar[ar2[0]-1]++;
                    ar[ar2[1]-1]++;
                }
                int c = 0;
                if (m % 2 == 0)
                    c = m / 2;
                else
                    c = m / 2 + 1;
                bool q = false;
                for (int i = 0; i < 5; i++)
                {
                    if(ar[i]>=3)
                    {
                        q = true;
                        break;
                    }
                }
                if(q || m ==0)
                    Console.WriteLine("WIN");
                else
                    Console.WriteLine("FAIL");
                Console.ReadKey();
           }
          catch { }
        }

    }
}


using System;

class Program
{
  static void Main(string[] args)
  {
    int[] array = new int[11];
    for(int i = 0; i < 11; i++)
    {
      array[i] = int.Parse(Console.ReadLine());
    }
    for(int i = 10; i >= 0; i--)
    {
      double a = Math.Sqrt(Math.Abs(array[i]));
      double b = Math.Pow(array[i], 3) * 5;
      double result = a + b;
      if(result <= 400)
      {
        Console.WriteLine(String.Format("f({0}) = {1:0.00}",  array[i], result));
      }
      else
      {
        Console.WriteLine(String.Format("f({0}) = MAGNA NIMIS!",  array[i]));
      }
    }
  }
}


using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using CompLib.Util;

public class Program
{
    private int N;
    private List<(int to, int num)>[] E;
    private int[] U, V;
    private int Max;

    private int R;
    private bool[] IsX;
    private bool Found;
    private int XSize;

    private int[] Len;
    private int[] Dist;
    private int TmpX;
    private int TmpY;

    void Scan()
    {
        var sc = new Scanner();
        N = sc.NextInt();
        E = new List<(int to, int num)>[N];
        U = new int[N - 1];
        V = new int[N - 1];
        for (int i = 0; i < N; i++)
        {
            E[i] = new List<(int to, int num)>();
        }

        for (int i = 0; i < N - 1; i++)
        {
            int u = sc.NextInt() - 1;
            int v = sc.NextInt() - 1;
            U[i] = u + 1;
            V[i] = v + 1;
            E[u].Add((v, i));
            E[v].Add((u, i));
        }

        Max = 2 * N * N / 9;
    }

    void SetFlag(int cur, int par)
    {
        foreach ((int to, int num) e in E[cur])
        {
            if (e.to == par) continue;
            SetFlag(e.to, cur);
        }

        IsX[cur] = true;
    }

    int Go(int cur, int par)
    {
        var ls = new List<(int to, int size)>();
        int size = 1;
        foreach (var e in E[cur])
        {
            if (e.to == par) continue;
            int tmp = Go(e.to, cur);
            ls.Add((e.to, tmp));
            size += tmp;
        }

        if (par != -1)
        {
            ls.Add((par, N - size));
        }

        if (!Found)
        {
            bool[,] dp = new bool[ls.Count + 1, N];
            dp[0, 0] = true;
            for (int i = 0; i < ls.Count; i++)
            {
                for (int j = 0; j < N; j++)
                {
                    if (dp[i, j])
                    {
                        dp[i + 1, j] = true;
                        dp[i + 1, j + ls[i].size] = true;
                    }
                }
            }

            int x = -1;
            for (int i = 0; i < N; i++)
            {
                if (!dp[ls.Count, i]) continue;
                int y = N - 1 - i;
                if (Max < (i + 1) * (y + 1))
                {
                    x = i;
                    break;
                }
            }

            if (x != -1)
            {
                XSize = x;
                R = cur;
                for (int i = ls.Count - 1; i >= 0; i--)
                {
                    if (x - ls[i].size >= 0 && dp[i, x - ls[i].size])
                    {
                        SetFlag(ls[i].to, cur);
                        x -= ls[i].size;
                    }
                }

                Found = true;
            }
        }

        return size;
    }

    // r、x,yの頂点を決める
    void SearchR()
    {
        IsX = new bool[N];
        Found = false;
        Go(0, -1);
        if (!Found) throw new Exception();
    }

    // 現在地、親、par-curが辺num
    void SetX(int cur, int par, int num)
    {
        Dist[cur] = TmpX++;
        if (par != -1)
        {
            Len[num] = Dist[cur] - Dist[par];
        }

        foreach ((int to, int num) e in E[cur])
        {
            if (e.to == par) continue;
            if (!IsX[e.to]) continue;
            SetX(e.to, cur, e.num);
        }
    }

    void SetY(int cur, int par, int num)
    {
        Dist[cur] = TmpY;
        TmpY += (XSize + 1);
        if (par != -1)
        {
            Len[num] = Dist[cur] - Dist[par];
        }

        foreach ((int to, int num) e in E[cur])
        {
            if (e.to == par) continue;
            if (IsX[e.to]) continue;
            SetY(e.to, cur, e.num);
        }
    }

    void SetLen()
    {
        // 辺の長さ
        Len = new int[N - 1];
        // R->頂点までの距離
        Dist = new int[N];
        // X側の頂点はRに近い順に距離1~Xを割り当てる
        // それぞれの頂点までの距離になるように辺の長さを割り当てる
        TmpX = 0;
        SetX(R, -1, -1);

        // Y (X+1)刻みで割り当てる
        TmpY = 0;
        SetY(R, -1, -1);
    }

    void Write()
    {
        var sb = new StringBuilder();
        for (int i = 0; i < N - 1; i++)
        {
            sb.AppendLine($"{U[i]} {V[i]} {Len[i]}");
        }

        Console.Write(sb);
    }

    public void Solve()
    {
        // ある頂点rを境目に2つに分ける
        // 片方x個 もう片方 y個 x + y + 1 = N
        // 片方でrからの距離 0~xをつくる
        // 残り x+1刻みで y個
        // 0 <= p < (x+1)(y+1)できる

        Scan();
        SearchR();
        SetLen();
        Write();
    }

    public static void Main(string[] args)
    {
        new Thread(new ThreadStart(new Program().Solve), 1 << 27).Start();
    }
}

namespace CompLib.Util
{
    using System;
    using System.Linq;

    class Scanner
    {
        private string[] _line;
        private int _index;
        private const char Separator = ' ';

        public Scanner()
        {
            _line = new string[0];
            _index = 0;
        }

        public string Next()
        {
            if (_index >= _line.Length)
            {
                string s;
                do
                {
                    s = Console.ReadLine();
                } while (s.Length == 0);

                _line = s.Split(Separator);
                _index = 0;
            }

            return _line[_index++];
        }

        public int NextInt() => int.Parse(Next());
        public long NextLong() => long.Parse(Next());
        public double NextDouble() => double.Parse(Next());
        public decimal NextDecimal() => decimal.Parse(Next());
        public char NextChar() => Next()[0];
        public char[] NextCharArray() => Next().ToCharArray();

        public string[] Array()
        {
            string s = Console.ReadLine();
            _line = s.Length == 0 ? new string[0] : s.Split(Separator);
            _index = _line.Length;
            return _line;
        }

        public int[] IntArray() => Array().Select(int.Parse).ToArray();
        public long[] LongArray() => Array().Select(long.Parse).ToArray();
        public double[] DoubleArray() => Array().Select(double.Parse).ToArray();
        public decimal[] DecimalArray() => Array().Select(decimal.Parse).ToArray();
    }
}


using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using CompLib.Util;

public class Program
{
    private int N;
    private List<(int to, int num)>[] E;
    private int[] U, V;
    private int Max;

    private int R;
    private bool[] IsX;
    private bool Found;
    private int XSize;

    private int[] Len;
    private int[] Dist;
    private int TmpX;
    private int TmpY;

    void Scan()
    {
        var sc = new Scanner();
        N = sc.NextInt();
        E = new List<(int to, int num)>[N];
        U = new int[N - 1];
        V = new int[N - 1];
        for (int i = 0; i < N; i++)
        {
            E[i] = new List<(int to, int num)>();
        }

        for (int i = 0; i < N - 1; i++)
        {
            int u = sc.NextInt() - 1;
            int v = sc.NextInt() - 1;
            U[i] = u + 1;
            V[i] = v + 1;
            E[u].Add((v, i));
            E[v].Add((u, i));
        }

        Max = 2 * N * N / 9;
    }

    void SetFlag(int cur, int par)
    {
        foreach ((int to, int num) e in E[cur])
        {
            if (e.to == par) continue;
            SetFlag(e.to, cur);
        }

        IsX[cur] = true;
    }

    int Go(int cur, int par)
    {
        var ls = new List<(int to, int size)>();
        int size = 1;
        foreach (var e in E[cur])
        {
            if (e.to == par) continue;
            int tmp = Go(e.to, cur);
            ls.Add((e.to, tmp));
            size += tmp;
        }

        if (par != -1)
        {
            ls.Add((par, N - size));
        }

        if (!Found)
        {
            bool[,] dp = new bool[ls.Count + 1, N];
            dp[0, 0] = true;
            for (int i = 0; i < ls.Count; i++)
            {
                for (int j = 0; j < N; j++)
                {
                    if (dp[i, j])
                    {
                        dp[i + 1, j] = true;
                        dp[i + 1, j + ls[i].size] = true;
                    }
                }
            }

            int x = -1;
            for (int i = 0; i < N; i++)
            {
                if (!dp[ls.Count, i]) continue;
                int y = N - 1 - i;
                if (Max < (i + 1) * (y + 1))
                {
                    x = i;
                    break;
                }
            }

            if (x != -1)
            {
                XSize = x;
                R = cur;
                for (int i = ls.Count - 1; i >= 0; i--)
                {
                    if (x - ls[i].size >= 0 && dp[i, x - ls[i].size])
                    {
                        SetFlag(ls[i].to, cur);
                        x -= ls[i].size;
                    }
                }

                Found = true;
            }
        }

        return size;
    }

    // r、x,yの頂点を決める
    void SearchR()
    {
        IsX = new bool[N];
        Found = false;
        Go(0, -1);
        if (!Found) throw new Exception();
    }

    // 現在地、親、par-curが辺num
    void SetX(int cur, int par, int num)
    {
        Dist[cur] = TmpX++;
        if (par != -1)
        {
            Len[num] = Dist[cur] - Dist[par];
        }

        foreach ((int to, int num) e in E[cur])
        {
            if (e.to == par) continue;
            if (!IsX[e.to]) continue;
            SetX(e.to, cur, e.num);
        }
    }

    void SetY(int cur, int par, int num)
    {
        Dist[cur] = TmpY;
        TmpY += (XSize + 1);
        if (par != -1)
        {
            Len[num] = Dist[cur] - Dist[par];
        }

        foreach ((int to, int num) e in E[cur])
        {
            if (e.to == par) continue;
            if (IsX[e.to]) continue;
            SetY(e.to, cur, e.num);
        }
    }

    void SetLen()
    {
        // 辺の長さ
        Len = new int[N - 1];
        // R->頂点までの距離
        Dist = new int[N];
        // X側の頂点はRに近い順に距離1~Xを割り当てる
        // それぞれの頂点までの距離になるように頂点の長さを割り当てる
        TmpX = 0;
        SetX(R, -1, -1);

        // Y (X+1)刻みで割り当てる
        TmpY = 0;
        SetY(R, -1, -1);
    }

    void Write()
    {
        var sb = new StringBuilder();
        for (int i = 0; i < N - 1; i++)
        {
            sb.AppendLine($"{U[i]} {V[i]} {Len[i]}");
        }

        Console.Write(sb);
    }

    public void Solve()
    {
        // ある頂点rを境目に2つに分ける
        // 片方x個 もう片方 y個 x + y + 1 = N
        // 片方でrからの距離 0~xをつくる
        // 残り x+1刻みで y個
        // 0 <= p < (x+1)(y+1)できる

        Scan();
        SearchR();
        SetLen();
        Write();
    }

    public static void Main(string[] args)
    {
        new Thread(new ThreadStart(new Program().Solve), 1 << 27).Start();
    }
}

namespace CompLib.Util
{
    using System;
    using System.Linq;

    class Scanner
    {
        private string[] _line;
        private int _index;
        private const char Separator = ' ';

        public Scanner()
        {
            _line = new string[0];
            _index = 0;
        }

        public string Next()
        {
            if (_index >= _line.Length)
            {
                string s;
                do
                {
                    s = Console.ReadLine();
                } while (s.Length == 0);

                _line = s.Split(Separator);
                _index = 0;
            }

            return _line[_index++];
        }

        public int NextInt() => int.Parse(Next());
        public long NextLong() => long.Parse(Next());
        public double NextDouble() => double.Parse(Next());
        public decimal NextDecimal() => decimal.Parse(Next());
        public char NextChar() => Next()[0];
        public char[] NextCharArray() => Next().ToCharArray();

        public string[] Array()
        {
            string s = Console.ReadLine();
            _line = s.Length == 0 ? new string[0] : s.Split(Separator);
            _index = _line.Length;
            return _line;
        }

        public int[] IntArray() => Array().Select(int.Parse).ToArray();
        public long[] LongArray() => Array().Select(long.Parse).ToArray();
        public double[] DoubleArray() => Array().Select(double.Parse).ToArray();
        public decimal[] DecimalArray() => Array().Select(decimal.Parse).ToArray();
    }
}


using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using CompLib.Util;

public class Program
{
    private int N;
    private List<(int to, int num)>[] E;
    private int[] U, V;
    private int Max;

    private int R;
    private bool[] IsX;
    private bool Found;
    private int XSize;

    private int[] Len;
    private int[] Dist;
    private int TmpX;
    private int TmpY;

    void Scan()
    {
        var sc = new Scanner();
        N = sc.NextInt();
        E = new List<(int to, int num)>[N];
        U = new int[N - 1];
        V = new int[N - 1];
        for (int i = 0; i < N; i++)
        {
            E[i] = new List<(int to, int num)>();
        }

        for (int i = 0; i < N - 1; i++)
        {
            int u = sc.NextInt() - 1;
            int v = sc.NextInt() - 1;
            U[i] = u + 1;
            V[i] = v + 1;
            E[u].Add((v, i));
            E[v].Add((u, i));
        }

        Max = 2 * N * N / 9;
    }

    void SetFlag(int cur, int par)
    {
        foreach ((int to, int num) e in E[cur])
        {
            if (e.to == par) continue;
            SetFlag(e.to, cur);
        }

        IsX[cur] = true;
    }

    int Go(int cur, int par)
    {
        var ls = new List<(int to, int size)>();
        int size = 1;
        foreach (var e in E[cur])
        {
            if (e.to == par) continue;
            int tmp = Go(e.to, cur);
            ls.Add((e.to, tmp));
            size += tmp;
        }

        // if (par != -1)
        // {
        //     ls.Add((par, N - size));
        // }

        if (!Found)
        {
            // 親側は処理が難しいので飛ばす
            // x,y逆になってもいいので問題ない
            bool[,] dp = new bool[ls.Count + 1, N];
            dp[0, 0] = true;
            for (int i = 0; i < ls.Count; i++)
            {
                for (int j = 0; j < N; j++)
                {
                    if (dp[i, j]) dp[i + 1, j + ls[i].size] = true;
                }
            }

            int x = -1;
            for (int i = 0; i < N; i++)
            {
                if (!dp[ls.Count, i]) continue;
                int y = N - 1 - i;
                if (Max < (i + 1) * (y + 1))
                {
                    x = i;
                    break;
                }
            }

            if (x != -1)
            {
                XSize = x;
                R = cur;
                for (int i = ls.Count - 1; i >= 0; i--)
                {
                    if (x - ls[i].size >= 0 && dp[i, x - ls[i].size])
                    {
                        SetFlag(ls[i].to, cur);
                        x -= ls[i].size;
                    }
                }

                Found = true;
            }
        }

        return size;
    }

    // r、x,yの頂点を決める
    void SearchR()
    {
        IsX = new bool[N];
        Found = false;
        Go(0, -1);
        if (!Found) throw new Exception();
    }

    // 現在地、親、par-curが辺num
    void SetX(int cur, int par, int num)
    {
        Dist[cur] = TmpX++;
        if (par != -1)
        {
            Len[num] = Dist[cur] - Dist[par];
        }

        foreach ((int to, int num) e in E[cur])
        {
            if (e.to == par) continue;
            if (!IsX[e.to]) continue;
            SetX(e.to, cur, e.num);
        }
    }

    void SetY(int cur, int par, int num)
    {
        Dist[cur] = TmpY;
        TmpY += (XSize + 1);
        if (par != -1)
        {
            Len[num] = Dist[cur] - Dist[par];
        }

        foreach ((int to, int num) e in E[cur])
        {
            if (e.to == par) continue;
            if (IsX[e.to]) continue;
            SetY(e.to, cur, e.num);
        }
    }

    void SetLen()
    {
        // 辺の長さ
        Len = new int[N - 1];
        // R->頂点までの距離
        Dist = new int[N];
        // X側の頂点はRに近い順に距離1~Xを割り当てる
        // それぞれの頂点までの距離になるように頂点の長さを割り当てる
        TmpX = 0;
        SetX(R, -1, -1);

        // Y (X+1)刻みで割り当てる
        TmpY = 0;
        SetY(R, -1, -1);
    }

    void Write()
    {
        var sb = new StringBuilder();
        for (int i = 0; i < N - 1; i++)
        {
            sb.AppendLine($"{U[i]} {V[i]} {Len[i]}");
        }

        Console.Write(sb);
    }

    public void Solve()
    {
        // ある頂点rを境目に2つに分ける
        // 片方x個 もう片方 y個 x + y + 1 = N
        // 片方でrからの距離 0~xをつくる
        // 残り x+1刻みで y個
        // 0 <= p < (x+1)(y+1)できる

        Scan();
        SearchR();
        SetLen();
        Write();
    }

    public static void Main(string[] args)
    {
        new Thread(new ThreadStart(new Program().Solve), 1 << 27).Start();
    }
}

namespace CompLib.Util
{
    using System;
    using System.Linq;

    class Scanner
    {
        private string[] _line;
        private int _index;
        private const char Separator = ' ';

        public Scanner()
        {
            _line = new string[0];
            _index = 0;
        }

        public string Next()
        {
            if (_index >= _line.Length)
            {
                string s;
                do
                {
                    s = Console.ReadLine();
                } while (s.Length == 0);

                _line = s.Split(Separator);
                _index = 0;
            }

            return _line[_index++];
        }

        public int NextInt() => int.Parse(Next());
        public long NextLong() => long.Parse(Next());
        public double NextDouble() => double.Parse(Next());
        public decimal NextDecimal() => decimal.Parse(Next());
        public char NextChar() => Next()[0];
        public char[] NextCharArray() => Next().ToCharArray();

        public string[] Array()
        {
            string s = Console.ReadLine();
            _line = s.Length == 0 ? new string[0] : s.Split(Separator);
            _index = _line.Length;
            return _line;
        }

        public int[] IntArray() => Array().Select(int.Parse).ToArray();
        public long[] LongArray() => Array().Select(long.Parse).ToArray();
        public double[] DoubleArray() => Array().Select(double.Parse).ToArray();
        public decimal[] DecimalArray() => Array().Select(decimal.Parse).ToArray();
    }
}


using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.IO;
using System.Globalization;
using System.Collections;

namespace Task
{

    #region MyIo

    internal class MyIo : IDisposable
    {
        private readonly TextReader inputStream;
        private readonly TextWriter outputStream = Console.Out;

        private string[] tokens;
        private int pointer;

        public MyIo()
#if  LOCAL_TEST
            : this(new StreamReader("input.txt"))
#else
            : this(System.Console.In)
#endif
        {

        }

        public MyIo(TextReader inputStream)
        {
            this.inputStream = inputStream;
        }

        public string NextLine()
        {
            try
            {
                return inputStream.ReadLine();
            }
            catch (IOException)
            {
                return null;
            }
        }

        public string NextString()
        {
            try
            {
                while (tokens == null || pointer >= tokens.Length)
                {
                    tokens = NextLine().Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
                    pointer = 0;
                }
                return tokens[pointer++];
            }
            catch (IOException)
            {
                return null;
            }
        }

        public int NextInt()
        {
            return Next<int>();
        }

        public long NextLong()
        {
            return Next<long>();
        }

        public T Next<T>()
        {
            return (T)Convert.ChangeType(NextString(), typeof(T));
        }

        public IEnumerable<T> NextSeq<T>(int n)
        {
            for (int i = 0; i < n; i++)
                yield return Next<T>();
        }

        public void Print(string format, params object[] args)
        {
            outputStream.Write(string.Format(CultureInfo.InvariantCulture, format, args));
        }

        public void PrintLine(string format, params object[] args)
        {
            Print(format, args);

            outputStream.WriteLine();
        }

        public void Print(bool o)
        {
            Print(o ? "YES" : "NO");
        }

        public void PrintLine(bool o)
        {
            PrintLine(o ? "YES" : "NO");
        }

        public void Print<T>(T o)
        {
            outputStream.Write(o);
        }

        public void PrintLine<T>(T o)
        {
            outputStream.WriteLine(o);
        }

        public void Close()
        {
            inputStream.Close();
            outputStream.Close();
        }

        void IDisposable.Dispose()
        {
            Close();

#if  LOCAL_TEST
            Console.ReadLine();
#endif
        }
    }

    public static class ListExtensions
    {
        public static T CycleGet<T>(this IList<T> self, int index)
        {
            var c = self.Count;
            return self[(index % c + c) % c];
        }

        public static IList<T> Shuffle<T>(this IList<T> self)
        {
            var rnd = new Random(DateTime.Now.Millisecond);

            var n = self.Count;

            while (n > 1)
            {
                n--;
                var k = rnd.Next(n + 1);
                var value = self[k];
                self[k] = self[n];
                self[n] = value;
            }

            return self;
        }

        public static IList<T> Fill<T>(this IList<T> self, T val)
        {
            for (int i = 0; i < self.Count; i++)
            {
                self[i] = val;
            }

            return self;
        }
    }

    public static class P
    {
        public static P<T1, T2> Create<T1, T2>(T1 key, T2 val)
        {
            return new P<T1, T2>(key, val);
        }
    }

    public class P<T1, T2>
    {
        private class PComparer : IComparer<P<T1, T2>>
        {
            private readonly bool? byKey;

            public PComparer(bool? byKey)
            {
                this.byKey = byKey;
            }

            public int Compare(P<T1, T2> x, P<T1, T2> y)
            {
                x = x ?? new P<T1, T2>();
                y = y ?? new P<T1, T2>();

                if (byKey == true)
                    return Comparer<T1>.Default.Compare(x.Key, y.Key);
                else if (byKey == false)
                    return Comparer<T2>.Default.Compare(x.Value, y.Value);
                else
                {
                    var tr = Comparer<T1>.Default.Compare(x.Key, y.Key);

                    if (tr != 0)
                        tr = Comparer<T2>.Default.Compare(x.Value, y.Value);

                    return tr;
                }
            }
        }

        public P()
        {
        }

        public P(T1 key, T2 val)
        {
            this.Key = key;
            this.Value = val;
        }

        public T1 Key
        {
            get;
            set;
        }

        public T2 Value
        {
            get;
            set;
        }

        public P<T1, T2> Clone()
        {
            return new P<T1, T2>(Key, Value);
        }

        public static IComparer<P<T1, T2>> KeyComparer
        {
            get { return new PComparer(true); }
        }

        public static IComparer<P<T1, T2>> ValueComparer
        {
            get { return new PComparer(false); }
        }

        public static implicit operator T1(P<T1, T2> obj)
        {
            return obj.Key;
        }

        public static implicit operator T2(P<T1, T2> obj)
        {
            return obj.Value;
        }

        public P<T1, T2> SetKey(T1 key)
        {
            Key = key;
            return this;
        }

        public P<T1, T2> SetValue(T2 value)
        {
            Value = value;
            return this;
        }

        public override string ToString()
        {
            return string.Format("Key: {0}, Value: {1}", Key, Value);
        }

        public override int GetHashCode()
        {
            int hash = 17;
            hash = hash * 31 + ((Equals(Key, default(T1))) ? 0 : Key.GetHashCode());
            hash = hash * 31 + ((Equals(Value, default(T1))) ? 0 : Key.GetHashCode());
            return hash;

        }
    }

    #endregion

    internal class Program
    {
        #region Program

        private readonly MyIo io;

        public Program(MyIo io)
        {
            this.io = io;
        }

        public static void Main(string[] args)
        {
            using (MyIo io = new MyIo())
            {
                new Program(io)
                    .Solve();
            }
        }

        #endregion
        public const long MOD = 1000000007;
        public const double EPS = 1e-14;

        private void Solve()
        {
            var a = io.NextInt();
            var b = io.NextInt();

            var sa = io.NextSeq<int>(a).Select(x => x - 1).ToArray();
            var isb = new int[1000000];

            isb.Fill(-1);

            var i = 0;

            for (; i < b; i++)
                isb[io.NextInt() - 1] = i;

            var res = 0;

            long[] q = new long[2 * a];

            i = 0;

            for (var j = 0; j < 2 * a; j++)
            {
                q[j] = isb[sa.CycleGet(j)];

                if (q[j] == -1)
                {
                    i = j + 1;//just skip and reset i=j for the next cycle so i=j+1 for current
                    continue;
                }

                if (q.CycleGet(j-1) > q[j])
                    q[j] += b;

                while (i <= j && q[j] - q[i] >= b || j - i + 1 > a)
                {
                    i++;
                }
                res = Math.Max(res, j - i + 1);
            }

            io.PrintLine(res);
        }
    }

}


using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.IO;
using System.Globalization;
using System.Collections;

namespace Task
{

    #region MyIo

    internal class MyIo : IDisposable
    {
        private readonly TextReader inputStream;
        private readonly TextWriter outputStream = Console.Out;

        private string[] tokens;
        private int pointer;

        public MyIo()
#if  LOCAL_TEST
            : this(new StreamReader("input.txt"))
#else
            : this(System.Console.In)
#endif
        {

        }

        public MyIo(TextReader inputStream)
        {
            this.inputStream = inputStream;
        }

        public string NextLine()
        {
            try
            {
                return inputStream.ReadLine();
            }
            catch (IOException)
            {
                return null;
            }
        }

        public string NextString()
        {
            try
            {
                while (tokens == null || pointer >= tokens.Length)
                {
                    tokens = NextLine().Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
                    pointer = 0;
                }
                return tokens[pointer++];
            }
            catch (IOException)
            {
                return null;
            }
        }

        public int NextInt()
        {
            return Next<int>();
        }

        public long NextLong()
        {
            return Next<long>();
        }

        public T Next<T>()
        {
            return (T)Convert.ChangeType(NextString(), typeof(T));
        }

        public IEnumerable<T> NextSeq<T>(int n)
        {
            for (int i = 0; i < n; i++)
                yield return Next<T>();
        }

        public void Print(string format, params object[] args)
        {
            outputStream.Write(string.Format(CultureInfo.InvariantCulture, format, args));
        }

        public void PrintLine(string format, params object[] args)
        {
            Print(format, args);

            outputStream.WriteLine();
        }

        public void Print(bool o)
        {
            Print(o ? "YES" : "NO");
        }

        public void PrintLine(bool o)
        {
            PrintLine(o ? "YES" : "NO");
        }

        public void Print<T>(T o)
        {
            outputStream.Write(o);
        }

        public void PrintLine<T>(T o)
        {
            outputStream.WriteLine(o);
        }

        public void Close()
        {
            inputStream.Close();
            outputStream.Close();
        }

        void IDisposable.Dispose()
        {
            Close();

#if  LOCAL_TEST
            Console.ReadLine();
#endif
        }
    }

    public static class ListExtensions
    {
        public static T CycleGet<T>(this IList<T> self, int index)
        {
            var c = self.Count;
            return self[(index % c + c) % c];
        }

        public static IList<T> Shuffle<T>(this IList<T> self)
        {
            var rnd = new Random(DateTime.Now.Millisecond);

            var n = self.Count;

            while (n > 1)
            {
                n--;
                var k = rnd.Next(n + 1);
                var value = self[k];
                self[k] = self[n];
                self[n] = value;
            }

            return self;
        }

        public static IList<T> Fill<T>(this IList<T> self, T val)
        {
            for (int i = 0; i < self.Count; i++)
            {
                self[i] = val;
            }

            return self;
        }
    }

    public static class P
    {
        public static P<T1, T2> Create<T1, T2>(T1 key, T2 val)
        {
            return new P<T1, T2>(key, val);
        }
    }

    public class P<T1, T2>
    {
        private class PComparer : IComparer<P<T1, T2>>
        {
            private readonly bool? byKey;

            public PComparer(bool? byKey)
            {
                this.byKey = byKey;
            }

            public int Compare(P<T1, T2> x, P<T1, T2> y)
            {
                x = x ?? new P<T1, T2>();
                y = y ?? new P<T1, T2>();

                if (byKey == true)
                    return Comparer<T1>.Default.Compare(x.Key, y.Key);
                else if (byKey == false)
                    return Comparer<T2>.Default.Compare(x.Value, y.Value);
                else
                {
                    var tr = Comparer<T1>.Default.Compare(x.Key, y.Key);

                    if (tr != 0)
                        tr = Comparer<T2>.Default.Compare(x.Value, y.Value);

                    return tr;
                }
            }
        }

        public P()
        {
        }

        public P(T1 key, T2 val)
        {
            this.Key = key;
            this.Value = val;
        }

        public T1 Key
        {
            get;
            set;
        }

        public T2 Value
        {
            get;
            set;
        }

        public P<T1, T2> Clone()
        {
            return new P<T1, T2>(Key, Value);
        }

        public static IComparer<P<T1, T2>> KeyComparer
        {
            get { return new PComparer(true); }
        }

        public static IComparer<P<T1, T2>> ValueComparer
        {
            get { return new PComparer(false); }
        }

        public static implicit operator T1(P<T1, T2> obj)
        {
            return obj.Key;
        }

        public static implicit operator T2(P<T1, T2> obj)
        {
            return obj.Value;
        }

        public P<T1, T2> SetKey(T1 key)
        {
            Key = key;
            return this;
        }

        public P<T1, T2> SetValue(T2 value)
        {
            Value = value;
            return this;
        }

        public override string ToString()
        {
            return string.Format("Key: {0}, Value: {1}", Key, Value);
        }

        public override int GetHashCode()
        {
            int hash = 17;
            hash = hash * 31 + ((Equals(Key, default(T1))) ? 0 : Key.GetHashCode());
            hash = hash * 31 + ((Equals(Value, default(T1))) ? 0 : Key.GetHashCode());
            return hash;

        }
    }

    #endregion

    internal class Program
    {
        #region Program

        private readonly MyIo io;

        public Program(MyIo io)
        {
            this.io = io;
        }

        public static void Main(string[] args)
        {
            using (MyIo io = new MyIo())
            {
                new Program(io)
                    .Solve();
            }
        }

        #endregion
        public const long MOD = 1000000007;
        public const double EPS = 1e-14;

        private void Solve()
        {
            var a = io.NextInt();
            var b = io.NextInt();

            var sa = io.NextSeq<int>(a).Select(x => x - 1).ToArray();
            var isb = new int[1000000];

            isb.Fill(-1);

            var i = 0;

            for (; i < b; i++)
                isb[io.NextInt() - 1] = i;

            var res = 0;

            long[] q = new long[2 * a];

            i = 0;

            for (var j = 0; j < 2 * a; j++)
            {
                q[j] = isb[sa.CycleGet(j)];

                if (q[j] == -1)
                {
                    i = j + 1;
                    continue;
                }

                q[j] += ((q.CycleGet(j - 1) - q[j] + b - 1) / b) * b;

                while (i <= j && q[j] - q[i] >= b || j - i + 1 > a)
                {
                    i++;
                }
                res = Math.Max(res, j - i + 1);
            }

            io.PrintLine(res);
        }
    }

}


using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.IO;
using System.Globalization;
using System.Collections;

namespace Task
{

    #region MyIo

    internal class MyIo : IDisposable
    {
        private readonly TextReader inputStream;
        private readonly TextWriter outputStream = Console.Out;

        private string[] tokens;
        private int pointer;

        public MyIo()
#if  LOCAL_TEST
            : this(new StreamReader("input.txt"))
#else
            : this(System.Console.In)
#endif
        {

        }

        public MyIo(TextReader inputStream)
        {
            this.inputStream = inputStream;
        }

        public string NextLine()
        {
            try
            {
                return inputStream.ReadLine();
            }
            catch (IOException)
            {
                return null;
            }
        }

        public string NextString()
        {
            try
            {
                while (tokens == null || pointer >= tokens.Length)
                {
                    tokens = NextLine().Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
                    pointer = 0;
                }
                return tokens[pointer++];
            }
            catch (IOException)
            {
                return null;
            }
        }

        public int NextInt()
        {
            return Next<int>();
        }

        public long NextLong()
        {
            return Next<long>();
        }

        public T Next<T>()
        {
            return (T)Convert.ChangeType(NextString(), typeof(T));
        }

        public IEnumerable<T> NextSeq<T>(int n)
        {
            for (int i = 0; i < n; i++)
                yield return Next<T>();
        }

        public void Print(string format, params object[] args)
        {
            outputStream.Write(string.Format(CultureInfo.InvariantCulture, format, args));
        }

        public void PrintLine(string format, params object[] args)
        {
            Print(format, args);

            outputStream.WriteLine();
        }

        public void Print(bool o)
        {
            Print(o ? "YES" : "NO");
        }

        public void PrintLine(bool o)
        {
            PrintLine(o ? "YES" : "NO");
        }

        public void Print<T>(T o)
        {
            outputStream.Write(o);
        }

        public void PrintLine<T>(T o)
        {
            outputStream.WriteLine(o);
        }

        public void Close()
        {
            inputStream.Close();
            outputStream.Close();
        }

        void IDisposable.Dispose()
        {
            Close();

#if  LOCAL_TEST
            Console.ReadLine();
#endif
        }
    }

    public static class ListExtensions
    {
        public static T CycleGet<T>(this IList<T> self, int index)
        {
            var c = self.Count;
            return self[(index % c + c) % c];
        }

        public static IList<T> Shuffle<T>(this IList<T> self)
        {
            var rnd = new Random(DateTime.Now.Millisecond);

            var n = self.Count;

            while (n > 1)
            {
                n--;
                var k = rnd.Next(n + 1);
                var value = self[k];
                self[k] = self[n];
                self[n] = value;
            }

            return self;
        }

        public static IList<T> Fill<T>(this IList<T> self, T val)
        {
            for (int i = 0; i < self.Count; i++)
            {
                self[i] = val;
            }

            return self;
        }
    }

    public static class P
    {
        public static P<T1, T2> Create<T1, T2>(T1 key, T2 val)
        {
            return new P<T1, T2>(key, val);
        }
    }

    public class P<T1, T2>
    {
        private class PComparer : IComparer<P<T1, T2>>
        {
            private readonly bool? byKey;

            public PComparer(bool? byKey)
            {
                this.byKey = byKey;
            }

            public int Compare(P<T1, T2> x, P<T1, T2> y)
            {
                x = x ?? new P<T1, T2>();
                y = y ?? new P<T1, T2>();

                if (byKey == true)
                    return Comparer<T1>.Default.Compare(x.Key, y.Key);
                else if (byKey == false)
                    return Comparer<T2>.Default.Compare(x.Value, y.Value);
                else
                {
                    var tr = Comparer<T1>.Default.Compare(x.Key, y.Key);

                    if (tr != 0)
                        tr = Comparer<T2>.Default.Compare(x.Value, y.Value);

                    return tr;
                }
            }
        }

        public P()
        {
        }

        public P(T1 key, T2 val)
        {
            this.Key = key;
            this.Value = val;
        }

        public T1 Key
        {
            get;
            set;
        }

        public T2 Value
        {
            get;
            set;
        }

        public P<T1, T2> Clone()
        {
            return new P<T1, T2>(Key, Value);
        }

        public static IComparer<P<T1, T2>> KeyComparer
        {
            get { return new PComparer(true); }
        }

        public static IComparer<P<T1, T2>> ValueComparer
        {
            get { return new PComparer(false); }
        }

        public static implicit operator T1(P<T1, T2> obj)
        {
            return obj.Key;
        }

        public static implicit operator T2(P<T1, T2> obj)
        {
            return obj.Value;
        }

        public P<T1, T2> SetKey(T1 key)
        {
            Key = key;
            return this;
        }

        public P<T1, T2> SetValue(T2 value)
        {
            Value = value;
            return this;
        }

        public override string ToString()
        {
            return string.Format("Key: {0}, Value: {1}", Key, Value);
        }

        public override int GetHashCode()
        {
            int hash = 17;
            hash = hash * 31 + ((Equals(Key, default(T1))) ? 0 : Key.GetHashCode());
            hash = hash * 31 + ((Equals(Value, default(T1))) ? 0 : Key.GetHashCode());
            return hash;

        }
    }

    #endregion

    internal class Program
    {
        #region Program

        private readonly MyIo io;

        public Program(MyIo io)
        {
            this.io = io;
        }

        public static void Main(string[] args)
        {
            using (MyIo io = new MyIo())
            {
                new Program(io)
                    .Solve();
            }
        }

        #endregion
        public const long MOD = 1000000007;
        public const double EPS = 1e-14;

        private void Solve()
        {
            var a = io.NextInt();
            var b = io.NextInt();

            var sa = io.NextSeq<int>(a).Select(x => x - 1).ToArray();
            var isb = new int[1000000];

            isb.Fill(-1);

            var i = 0;

            for (; i < b; i++)
                isb[io.NextInt() - 1] = i;

            var res = 0;

            long[] q = new long[2 * a];

            i = 0;

            long jp = 0;

            for (var j = 0; j < 2 * a; j++)
            {
                q[j] = isb[sa.CycleGet(j)];

                if (q[j] != -1)
                {

                    q[j] += ((jp - q[j] + b - 1) / b) * b;

                    while (i <= j && q[j] - q[i] >= b || j - i + 1 > a)
                    {
                        i++;
                    }
                    res = Math.Max(res, j - i + 1);
                }
                else
                {
                    i = j + 1;//just skip and reset i=j for the next cycle so i=j+1 for current
                }

                jp = q[j];
            }

            io.PrintLine(res);
        }
    }

}


using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.IO;
using System.Globalization;
using System.Collections;

namespace Task
{

    #region MyIo

    internal class MyIo : IDisposable
    {
        private readonly TextReader inputStream;
        private readonly TextWriter outputStream = Console.Out;

        private string[] tokens;
        private int pointer;

        public MyIo()
#if  LOCAL_TEST
            : this(new StreamReader("input.txt"))
#else
            : this(System.Console.In)
#endif
        {

        }

        public MyIo(TextReader inputStream)
        {
            this.inputStream = inputStream;
        }

        public string NextLine()
        {
            try
            {
                return inputStream.ReadLine();
            }
            catch (IOException)
            {
                return null;
            }
        }

        public string NextString()
        {
            try
            {
                while (tokens == null || pointer >= tokens.Length)
                {
                    tokens = NextLine().Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
                    pointer = 0;
                }
                return tokens[pointer++];
            }
            catch (IOException)
            {
                return null;
            }
        }

        public int NextInt()
        {
            return Next<int>();
        }

        public long NextLong()
        {
            return Next<long>();
        }

        public T Next<T>()
        {
            return (T)Convert.ChangeType(NextString(), typeof(T));
        }

        public IEnumerable<T> NextSeq<T>(int n)
        {
            for (int i = 0; i < n; i++)
                yield return Next<T>();
        }

        public void Print(string format, params object[] args)
        {
            outputStream.Write(string.Format(CultureInfo.InvariantCulture, format, args));
        }

        public void PrintLine(string format, params object[] args)
        {
            Print(format, args);

            outputStream.WriteLine();
        }

        public void Print(bool o)
        {
            Print(o ? "YES" : "NO");
        }

        public void PrintLine(bool o)
        {
            PrintLine(o ? "YES" : "NO");
        }

        public void Print<T>(T o)
        {
            outputStream.Write(o);
        }

        public void PrintLine<T>(T o)
        {
            outputStream.WriteLine(o);
        }

        public void Close()
        {
            inputStream.Close();
            outputStream.Close();
        }

        void IDisposable.Dispose()
        {
            Close();

#if  LOCAL_TEST
            Console.ReadLine();
#endif
        }
    }

    public static class ListExtensions
    {
        public static T CycleGet<T>(this IList<T> self, int index)
        {
            var c = self.Count;
            return self[(index % c + c) % c];
        }

        public static IList<T> Shuffle<T>(this IList<T> self)
        {
            var rnd = new Random(DateTime.Now.Millisecond);

            var n = self.Count;

            while (n > 1)
            {
                n--;
                var k = rnd.Next(n + 1);
                var value = self[k];
                self[k] = self[n];
                self[n] = value;
            }

            return self;
        }

        public static IList<T> Fill<T>(this IList<T> self, T val)
        {
            for (int i = 0; i < self.Count; i++)
            {
                self[i] = val;
            }

            return self;
        }
    }

    public static class P
    {
        public static P<T1, T2> Create<T1, T2>(T1 key, T2 val)
        {
            return new P<T1, T2>(key, val);
        }
    }

    public class P<T1, T2>
    {
        private class PComparer : IComparer<P<T1, T2>>
        {
            private readonly bool? byKey;

            public PComparer(bool? byKey)
            {
                this.byKey = byKey;
            }

            public int Compare(P<T1, T2> x, P<T1, T2> y)
            {
                x = x ?? new P<T1, T2>();
                y = y ?? new P<T1, T2>();

                if (byKey == true)
                    return Comparer<T1>.Default.Compare(x.Key, y.Key);
                else if (byKey == false)
                    return Comparer<T2>.Default.Compare(x.Value, y.Value);
                else
                {
                    var tr = Comparer<T1>.Default.Compare(x.Key, y.Key);

                    if (tr != 0)
                        tr = Comparer<T2>.Default.Compare(x.Value, y.Value);

                    return tr;
                }
            }
        }

        public P()
        {
        }

        public P(T1 key, T2 val)
        {
            this.Key = key;
            this.Value = val;
        }

        public T1 Key
        {
            get;
            set;
        }

        public T2 Value
        {
            get;
            set;
        }

        public P<T1, T2> Clone()
        {
            return new P<T1, T2>(Key, Value);
        }

        public static IComparer<P<T1, T2>> KeyComparer
        {
            get { return new PComparer(true); }
        }

        public static IComparer<P<T1, T2>> ValueComparer
        {
            get { return new PComparer(false); }
        }

        public static implicit operator T1(P<T1, T2> obj)
        {
            return obj.Key;
        }

        public static implicit operator T2(P<T1, T2> obj)
        {
            return obj.Value;
        }

        public P<T1, T2> SetKey(T1 key)
        {
            Key = key;
            return this;
        }

        public P<T1, T2> SetValue(T2 value)
        {
            Value = value;
            return this;
        }

        public override string ToString()
        {
            return string.Format("Key: {0}, Value: {1}", Key, Value);
        }

        public override int GetHashCode()
        {
            int hash = 17;
            hash = hash * 31 + ((Equals(Key, default(T1))) ? 0 : Key.GetHashCode());
            hash = hash * 31 + ((Equals(Value, default(T1))) ? 0 : Key.GetHashCode());
            return hash;

        }
    }

    #endregion

    internal class Program
    {
        #region Program

        private readonly MyIo io;

        public Program(MyIo io)
        {
            this.io = io;
        }

        public static void Main(string[] args)
        {
            using (MyIo io = new MyIo())
            {
                new Program(io)
                    .Solve();
            }
        }

        #endregion
        public const long MOD = 1000000007;
        public const double EPS = 1e-14;

        private void Solve()
        {
            var a = io.NextInt();
            var b = io.NextInt();

            var sa = io.NextSeq<int>(a).Select(x => x - 1).ToArray();
            var isb = new int[1000000];

            isb.Fill(-1);

            var i = 0;

            for (; i < b; i++)
                isb[io.NextInt() - 1] = i;

            var res = 0;

            long[] q = new long[2 * a];

            i = 0;

            for (var j = 0; j < 2 * a; j++)
            {
                q[j] = isb[sa.CycleGet(j)];

                if (q[j] == -1)
                {
                    i = j + 1;//just skip and reset i=j for the next cycle so i=j+1 for current
                    continue;
                }

                while(q.CycleGet(j - 1) > q[j])
                    q[j] += b;

                while (i <= j && q[j] - q[i] >= b || j - i + 1 > a)
                {
                    i++;
                }
                res = Math.Max(res, j - i + 1);
            }

            io.PrintLine(res);
        }
    }

}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

class Program
{
	int n, m, res;
	int mod = 1000000007;
	int add(int x, int y)
	{
		x += y;
		return x < mod ? x : x - mod;
	}
	int mul(int x, int y)
	{
		return Convert.ToInt32(Convert.ToInt64(x) * y % mod);
	}

	int gcd(int x, int y)
	{
		return y != 0 ? gcd(y, x % y) : x;
	}
	private int[] x = new int[6];
	void dfs(int i)
	{
		if (i == 6)
		{
			if ((x[0] * x[3] + x[2] * x[5] + x[4] * x[1] + x[1] * x[2] + x[3] * x[4] + x[5] * x[0]) % 2 == 0)
			{
				int now = 1;
				for(int j=0; j<6; j++)
					if (j % 2 == 0)
						now = mul(now, x[j] == 1 ? (n + 1) / 2 : n / 2 + 1);
					else
						now = mul(now, x[j] == 1 ? (m + 1) / 2 : m / 2 + 1);
				res = add(res, now);
			}
			return;
		}
		x[i] = 0;
		dfs(i + 1);
		x[i] = 1;
		dfs(i + 1);
	}
	void run()
	{
		String[] str = Console.ReadLine().Split(' ');
		n = Convert.ToInt32(str[0]);
		m = Convert.ToInt32(str[1]);
		res = 0;
		dfs(0);
		int res2 = 0;
		for (int i = 0; i <= n; i++)
			for (int j = 0; j <= m; j++)
				if (i + j > 0)
				{
					int x = gcd(i, j) - 1;
					res2 = add(res2, mul(i > 0 && j > 0 ? x * 2 : x, (n + 1 - i) * (m + 1 - j)));
				}

		int q = (n + 1) * (m + 1);
		res2 = add(res2, Convert.ToInt32(Convert.ToInt64(q) * (q - 1) / 2 % mod));
		res2 = mul(res2, 6);
		res2 = add(res2, q);
		Console.WriteLine(add(res, mod - res2));
	}
	static void Main(String[] args)
	{
		new Program().run();
	}
}


using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;

class Solution
{

    static void Main(String[] args)
    {
        string one = "0469AD";
        string two = "8B";
        string e = long.Parse(Console.ReadLine()).ToString("X");

        int count = 0;
        for (int i = 0; i < e.Length; i++)
        {
            if (one.Contains(e[i])) count++;
            else if (two.Contains(e[i])) count += 2;
        }
        Console.WriteLine(count);
        Console.Read();
    }
}


using System;
namespace ConsoleApplication3
{
    class Program
    {
        // FEDCBA9876543210
        // 0010211201010001
        // 543210

        static void Main(string[] args)
        {
            var n = int.Parse(Console.ReadLine());
            if (n == 0)
            {
                Console.WriteLine("1");
                return;
            }
            var r = 0;

            while (n > 0)
            {
                switch (n % 16)
                {
                    case 0:
                    case 4:
                    case 6:
                    case 9:
                    case 10:
                    case 13:
                        r++;
                        break;
                    case 8:
                    case 11:
                        r += 2;
                        break;
                }

                n /= 16;
            }
            Console.WriteLine(r);
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace В
{
    class B
    {
        static void Main(string[] args)
        {
            string inp1 = Console.ReadLine();
            int n = Int32.Parse(inp1.Split(' ')[0].Trim()); //  подъезды
            int m = Int32.Parse(inp1.Split(' ')[1].Trim()); // этажи
            int k = Int32.Parse(inp1.Split(' ')[2].Trim()); // квартиры на этаже
            inp1 = Console.ReadLine();
            int a = Int32.Parse(inp1.Split(' ')[0].Trim()) - 1;
            int b = Int32.Parse(inp1.Split(' ')[1].Trim()) - 1;
            int nkm = n * m * k;
            int mk = m * k; // квартир в подъезде
            int a_n = a / mk;
            int b_n = b / mk;
            int a_m = ( a - a_n * mk ); //
            int b_m = ( b - b_n * mk );

            int t = 0;

            int ln = Math.Abs( b_n - a_n );
            t += 15 * Math.Min( ln, n - ln );
            if( t == 0 )
            {
                int floors = Math.Abs(a_m / k - b_m / k );
                t += Math.Min(floors * 5, 10 + floors);
            } else
            {
                int floorsa = a_m / k;
                t += Math.Min(floorsa * 5, 10 + floorsa);
                int floorsb = b_m / k;
                t += Math.Min(floorsb * 5, 10 + floorsb);
            }

            Console.WriteLine(t.ToString());
        }
    }
}


using System;
using System.IO;
class Program
{
    static void Main()
    {
        int n1, m1, n2, m2, res;
        string[] h = Console.ReadLine().Split(new char[] { ' ' });
        int n = int.Parse(h[0]);
        int m = int.Parse(h[1]);
        int k = int.Parse(h[2]);
        h = Console.ReadLine().Split(new char[] { ' ' });
        int A1 = int.Parse(h[0]);
        int A2 = int.Parse(h[1]);
        if (A1 % (m * k) == 0)
        {
            n1 = A1 / (m * k);
        }
        else
        {
            n1 = A1 / (m * k) + 1;
        }
        if ((A1 - (n1 - 1) * m * k) % k == 0)
        {
            m1 = (A1 - (n1 - 1) * m * k) / k;
        }
        else
        {
            m1 = (A1 - (n1 - 1) * m * k) / k + 1;
        }
        if (A2 % (m * k) == 0)
        {
            n2 = A2 / (m * k);
        }
        else
        {
            n2 = A2 / (m * k) + 1;
        }
        if ((A2 - (n2 - 1) * m * k) % k == 0)
        {
            m2 = (A2 - (n2 - 1) * m * k) / k;
        }
        else
        {
            m2 = (A2 - (n2 - 1) * m * k) / k + 1;
        }
        if (n1 == n2)
        {
            if (m1 == m2)
            {
                Console.WriteLine(0);
            }
            else
            {
                if (Math.Abs(m1 - m2) >= 3)
                {
                    Console.WriteLine(10 + Math.Abs(m1 - m2));
                }
                else
                {
                    Console.WriteLine(5 * Math.Abs(m1 - m2));
                }
            }
        }
        else
        {
            if (n1 < n2)
            {
                if (n2 - n1 < n - n2 + n1)
                {
                    if (m1 >= 4)
                    {
                        if (m2 >= 4)
                        {
                            Console.WriteLine(10 + m1 - 1 + (n2 - n1) * 15 + 10 + m2 - 1);
                        }
                        else
                        {
                            Console.WriteLine(10 + m1 - 1 + (n2 - n1) * 15 + 5 * (m2 - 1));
                        }
                    }
                    else
                    {
                        if (m2 >= 4)
                        {
                            Console.WriteLine(5 * (m1 - 1) + (n2 - n1) * 15 + 10 + m2 - 1);
                        }
                        else
                        {
                            Console.WriteLine(5 * (m1 - 1) + (n2 - n1) * 15 + 5 * (m2 - 1));
                        }
                    }

                }
                else
                {
                    if (m1 >= 4)
                    {
                        if (m2 >= 4)
                        {
                            Console.WriteLine(10 + m1 - 1 + (n - n2 + n1) * 15 + 10 + m2 - 1);
                        }
                        else
                        {
                            Console.WriteLine(10 + m1 - 1 + (n - n2 + n1) * 15 + 5 * (m2 - 1));
                        }
                    }
                    else
                    {
                        if (m2 >= 4)
                        {
                            Console.WriteLine(5 * (m1 - 1) + (n - n2 + n1) * 15 + 10 + m2 - 1);
                        }
                        else
                        {
                            Console.WriteLine(5 * (m1 - 1) + (n - n2 + n1) * 15 + 5 * (m2 - 1));
                        }
                    }
                }
            }
            else
            {
                if (n1 - n2 < n - n1 + n2)
                {
                    if (m1 >= 4)
                    {
                        if (m2 >= 4)
                        {
                            Console.WriteLine(10 + m1 - 1 + (n1 - n2) * 15 + 10 + m2 - 1);
                        }
                        else
                        {
                            Console.WriteLine(10 + m1 - 1 + (n1 - n2) * 15 + 5 * (m2 - 1));
                        }
                    }
                    else
                    {
                        if (m2 >= 4)
                        {
                            Console.WriteLine(5 * (m1 - 1) + (n1 - n2) * 15 + 10 + m2 - 1);
                        }
                        else
                        {
                            Console.WriteLine(5 * (m1 - 1) + (n1 - n2) * 15 + 5 * (m2 - 1));
                        }
                    }
                }
                else
                {
                    if (m1 >= 4)
                    {
                        if (m2 >= 4)
                        {
                            Console.WriteLine(10 + m1 - 1 + (n - n1 + n2) * 15 + 10 + m2 - 1);
                        }
                        else
                        {
                            Console.WriteLine(10 + m1 - 1 + (n - n1 + n2) * 15 + 5 * (m2 - 1));
                        }
                    }
                    else
                    {
                        if (m2 >= 4)
                        {
                            Console.WriteLine(5 * (m1 - 1) + (n - n1 + n2) * 15 + 10 + m2 - 1);
                        }
                        else
                        {
                            Console.WriteLine(5 * (m1 - 1) + (n - n1 + n2) * 15 + 5 * (m2 - 1));
                        }
                    }
                }
            }
        }
    }
}


using System;
using System.Linq;

namespace TheTournamentC1
{
    partial class TheTournamentC1
    {
        static void Main(string[] args)
        {
            int n, k, min;
            int[] points, effort, record, minEffort;

            n = NextInt();
            k = NextInt();

            points = new int[n];
            effort = new int[n];
            record = new int[n];
            minEffort = new int[2];

            for (int i = 0; i < n; i++)
            {
                points[i] = NextInt() + 1;
                effort[i] = NextInt();
                record[i] = 0;
            }

            minEffort[0] = Solve(0, k, 1, 0, 0, (int[])points.Clone(), (int[])effort.Clone(), (int[])record.Clone());
            minEffort[1] = Solve(0, k, 0, 0, 0, (int[])points.Clone(), (int[])effort.Clone(), (int[])record.Clone());

            min = minEffort.Min();
            min = min == int.MaxValue ? -1 : min;

            Console.WriteLine(min);
        }

        private static int Solve(int fighter, int k, int win, int currentPoints, int currentEffort, int[] points, int[] effort, int[] record)
        {
            int[] minEffort = new int[2];

            if (win == 1)
            {
                currentPoints++;
                currentEffort += effort[fighter];
                points[fighter]--;
                record[fighter] = 1;
            }

            fighter++;

            if (fighter < points.Length)
            {
                minEffort[0] = Solve(fighter, k, 1, currentPoints, currentEffort, (int[])points.Clone(), (int[])effort.Clone(), (int[])record.Clone());
                minEffort[1] = Solve(fighter, k, 0, currentPoints, currentEffort, (int[])points.Clone(), (int[])effort.Clone(), (int[])record.Clone());
            }
            else
            {
                if (IsWithinKRank((int[])points.Clone(), currentPoints, k, (int[])record.Clone()))
                    return currentEffort;
                else
                    return int.MaxValue;
            }

            return minEffort.Min();
        }

        private static bool IsWithinKRank(int[] points, int currentPoints, int k, int[] record)
        {
            int n = points.Length, rank = n + 1;
            int[] fighters = Enumerable.Range(0, n).ToArray();

            Array.Sort(points, fighters);

            for (int i = 0; i < n; i++)
            {
                if (currentPoints > points[i] || (currentPoints == points[i] && record[fighters[i]] == 1))
                    rank--;
            }

            return rank <= k;
        }
    }

    partial class TheTournamentC1
    {
        static string[] tokens = new string[0];
        static int cur_token = 0;

        static void ReadArray(char sep)
        {
            cur_token = 0;
            tokens = Console.ReadLine().Split(sep);
        }

        static int ReadInt()
        {
            return int.Parse(Console.ReadLine());
        }

        static long ReadLong()
        {
            return long.Parse(Console.ReadLine());
        }

        static int NextInt()
        {
            if (cur_token == tokens.Length)
                ReadArray(' ');
            return int.Parse(tokens[cur_token++]);
        }

        static long NextLong()
        {
            if (cur_token == tokens.Length)
                ReadArray(' ');
            return long.Parse(tokens[cur_token++]);
        }

        static double NextDouble()
        {
            if (cur_token == tokens.Length)
                ReadArray(' ');
            return double.Parse(tokens[cur_token++]);
        }

        static decimal NextDecimal()
        {
            if (cur_token == tokens.Length)
                ReadArray(' ');
            return decimal.Parse(tokens[cur_token++]);
        }

        static string NextToken()
        {
            if (cur_token == tokens.Length)
                ReadArray(' ');
            return tokens[cur_token++];
        }

        static string ReadLine()
        {
            return Console.ReadLine();
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using System.Diagnostics;
using System.Numerics;
using static System.Console;
using static System.Convert;
using static System.Math;
using static Template;
using Pi = Pair<int, int>;

class Solver
{
    public void Solve(Scanner sc)
    {
        int N, K;
        sc.Make(out N, out K);
        ModInt.Build(K + 1);
        var F = new ModInt[K + 2];
        for (int i = 1; i < K + 2; i++)
        {
            F[i] = ModInt.Pow(i, K) + F[i - 1];
        }
        if (N <= K + 1) Fail(F[N]);
        WriteLine(LagrangePolynomial(F, N));
    }
    public ModInt LagrangePolynomial(ModInt[] Y,int T,int a=0,int d = 1)
    {
        if (T < Y.Length) return Y[T];
        ModInt[] left = new ModInt[Y.Length], right = new ModInt[Y.Length];
        left[0] = right[Y.Length - 1] = 1;
        for (int i = 0; i < Y.Length-1; i++)
        {
            left[i + 1] = left[i] * (T - a - d * i);
        }
        for (int i = Y.Length - 2; i >= 0; i--)
        {
            right[i] = right[i + 1] * (T - a - d * (i + 1));
        }
        ModInt res = 0;
        for (int i = 0; i < Y.Length; i++)
        {
            ModInt r = Y[i] * left[i] * right[i] * ModInt.FacInv(i) * ModInt.FacInv(Y.Length - i - 1);
            if ((Y.Length - i - 1) % 2 == 0) res += r;
            else res -= r;
        }
        return res;
    }
}

public struct ModInt
{
    public const long MOD = (int)1e9 + 7;
    //public const long MOD = 998244353;
    public long Value { get; set; }
    public ModInt(long n = 0) { Value = n; }
    private static ModInt[] fac;//i!
    private static ModInt[] inv;//1/i
    private static ModInt[] facinv;//1/(i!)
    public override string ToString() => Value.ToString();
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static ModInt operator +(ModInt l, ModInt r)
    {
        l.Value += r.Value;
        if (l.Value >= MOD) l.Value -= MOD;
        return l;
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static ModInt operator -(ModInt l, ModInt r)
    {
        l.Value -= r.Value;
        if (l.Value < 0) l.Value += MOD;
        return l;
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static ModInt operator *(ModInt l, ModInt r) => new ModInt(l.Value * r.Value % MOD);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static ModInt operator /(ModInt l, ModInt r) => l * Pow(r, MOD - 2);
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static implicit operator long(ModInt l) => l.Value;
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static implicit operator ModInt(long n)
    {
        n %= MOD; if (n < 0) n += MOD;
        return new ModInt(n);
    }

    public static ModInt Pow(ModInt m, long n)
    {
        if (n == 0) return 1;
        if (n % 2 == 0) return Pow(m * m, n >> 1);
        else return Pow(m * m, n >> 1) * m;
    }

    public static void Build(int n)
    {
        fac = new ModInt[n + 1];
        facinv = new ModInt[n + 1];
        inv = new ModInt[n + 1];
        inv[1] = 1;
        fac[0] = fac[1] = 1;
        facinv[0] = facinv[1] = 1;
        for (var i = 2; i <= n; i++)
        {
            fac[i] = fac[i - 1] * i;
            inv[i] = MOD - inv[MOD % i] * (MOD / i);
            facinv[i] = facinv[i - 1] * inv[i];
        }
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static ModInt Fac(ModInt n) => fac[n];
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static ModInt Inv(ModInt n) => inv[n];
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static ModInt FacInv(ModInt n) => facinv[n];
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static ModInt Comb(ModInt n, ModInt r)
    {
        if (n < r) return 0;
        if (n == r) return 1;
        var calc = fac[n];
        calc = calc * facinv[r];
        calc = calc * facinv[n - r];
        return calc;
    }
}
#region Template
public static class Template
{
    static void Main(string[] args)
    {
        Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false });
        new Solver().Solve(new Scanner());
        Console.Out.Flush();
    }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool chmin<T>(ref T a, T b) where T : IComparable<T> { if (a.CompareTo(b) > 0) { a = b; return true; } return false; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static bool chmax<T>(ref T a, T b) where T : IComparable<T> { if (a.CompareTo(b) < 0) { a = b; return true; } return false; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static void swap<T>(ref T a, ref T b) { var t = b; b = a; a = t; }
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static void swap<T>(this IList<T> A, int i, int j) { var t = A[i]; A[i] = A[j]; A[j] = t; }
    public static T[] Create<T>(int n, Func<T> f) { var rt = new T[n]; for (var i = 0; i < rt.Length; ++i) rt[i] = f(); return rt; }
    public static T[] Create<T>(int n, Func<int, T> f) { var rt = new T[n]; for (var i = 0; i < rt.Length; ++i) rt[i] = f(i); return rt; }
    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> A) => A.OrderBy(v => Guid.NewGuid());
    public static int CompareTo<T>(this T[] A, T[] B, Comparison<T> cmp = null) { cmp = cmp ?? Comparer<T>.Default.Compare; for (var i = 0; i < Min(A.Length, B.Length); i++) { int c = cmp(A[i], B[i]); if (c > 0) return 1; else if (c < 0) return -1; } if (A.Length == B.Length) return 0; if (A.Length > B.Length) return 1; else return -1; }
    public static int MaxElement<T>(this IList<T> A, Comparison<T> cmp = null) { cmp = cmp ?? Comparer<T>.Default.Compare; T max = A[0]; int rt = 0; for (int i = 1; i < A.Count; i++) if (cmp(max, A[i]) < 0) { max = A[i]; rt = i; } return rt; }
    public static T PopBack<T>(this List<T> A) { var v = A[A.Count - 1]; A.RemoveAt(A.Count - 1); return v; }
    public static void Fail<T>(T s) { Console.WriteLine(s); Console.Out.Close(); Environment.Exit(0); }
}
public class Scanner
{
    public string Str => Console.ReadLine().Trim();
    public int Int => int.Parse(Str);
    public long Long => long.Parse(Str);
    public double Double => double.Parse(Str);
    public int[] ArrInt => Str.Split(' ').Select(int.Parse).ToArray();
    public long[] ArrLong => Str.Split(' ').Select(long.Parse).ToArray();
    public char[][] Grid(int n) => Create(n, () => Str.ToCharArray());
    public int[] ArrInt1D(int n) => Create(n, () => Int);
    public long[] ArrLong1D(int n) => Create(n, () => Long);
    public int[][] ArrInt2D(int n) => Create(n, () => ArrInt);
    public long[][] ArrLong2D(int n) => Create(n, () => ArrLong);
    private Queue<string> q = new Queue<string>();
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public T Next<T>() { if (q.Count == 0) foreach (var item in Str.Split(' ')) q.Enqueue(item); return (T)Convert.ChangeType(q.Dequeue(), typeof(T)); }
    public void Make<T1>(out T1 v1) => v1 = Next<T1>();
    public void Make<T1, T2>(out T1 v1, out T2 v2) { v1 = Next<T1>(); v2 = Next<T2>(); }
    public void Make<T1, T2, T3>(out T1 v1, out T2 v2, out T3 v3) { Make(out v1, out v2); v3 = Next<T3>(); }
    public void Make<T1, T2, T3, T4>(out T1 v1, out T2 v2, out T3 v3, out T4 v4) { Make(out v1, out v2, out v3); v4 = Next<T4>(); }
    public void Make<T1, T2, T3, T4, T5>(out T1 v1, out T2 v2, out T3 v3, out T4 v4, out T5 v5) { Make(out v1, out v2, out v3, out v4); v5 = Next<T5>(); }
    public void Make<T1, T2, T3, T4, T5, T6>(out T1 v1, out T2 v2, out T3 v3, out T4 v4, out T5 v5, out T6 v6) { Make(out v1, out v2, out v3, out v4, out v5); v6 = Next<T6>(); }
    //public (T1, T2) Make<T1, T2>() { Make(out T1 v1, out T2 v2); return (v1, v2); }
    //public (T1, T2, T3) Make<T1, T2, T3>() { Make(out T1 v1, out T2 v2, out T3 v3); return (v1, v2, v3); }
    //public (T1, T2, T3, T4) Make<T1, T2, T3, T4>() { Make(out T1 v1, out T2 v2, out T3 v3, out T4 v4); return (v1, v2, v3, v4); }
}
public class Pair<T1, T2> : IComparable<Pair<T1, T2>>
{
    public T1 v1;
    public T2 v2;
    public Pair() { }
    public Pair(T1 v1, T2 v2)
    { this.v1 = v1; this.v2 = v2; }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public int CompareTo(Pair<T1, T2> p)
    {
        var c = Comparer<T1>.Default.Compare(v1, p.v1);
        if (c == 0)
            c = Comparer<T2>.Default.Compare(v2, p.v2);
        return c;
    }
    public override string ToString() => $"{v1.ToString()} {v2.ToString()}";
    public void Deconstruct(out T1 a, out T2 b) { a = v1; b = v2; }
}

public class Pair<T1, T2, T3> : Pair<T1, T2>, IComparable<Pair<T1, T2, T3>>
{
    public T3 v3;
    public Pair() : base() { }
    public Pair(T1 v1, T2 v2, T3 v3) : base(v1, v2)
    { this.v3 = v3; }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public int CompareTo(Pair<T1, T2, T3> p)
    {
        var c = base.CompareTo(p);
        if (c == 0)
            c = Comparer<T3>.Default.Compare(v3, p.v3);
        return c;
    }
    public override string ToString() => $"{base.ToString()} {v3.ToString()}";
    public void Deconstruct(out T1 a, out T2 b, out T3 c) { Deconstruct(out a, out b); c = v3; }
}
#endregion


using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Collections.Generic;
using System.Diagnostics;
using System.Numerics;
using Enu = System.Linq.Enumerable;

class Program
{
    static readonly int Mod = (int)1e9 + 7;

    public void Solve()
    {
        int N = Reader.Int();
        int K = Reader.Int();
        long[] Y = new long[K + 2];

        for (int i = 1; i < Y.Length; i++)
            Y[i] = (Y[i - 1] + ModPower(i, K, Mod)) % Mod;

        long ans = new LagrangeInterpolation(Y, Mod).Get(N);
        Console.WriteLine(ans);
        Console.ReadLine();
    }

    class LagrangeInterpolation
    {
        readonly int N;
        readonly long M;
        readonly long[] Y, C;

        public LagrangeInterpolation(long[] Y, long mod)
        {
            this.N = Y.Length - 1;
            this.M = mod;
            this.Y = Y;
            this.C = new long[N + 1];
            long q = 1;
            for (int i = 1; i <= N; i++)
                q = q * Mod(-i) % mod;
            C[0] = Mod(Y[0] * ModInverse(q, mod));
            for (int i = 1; i <= N; i++)
            {
                q = Mod(q * ModInverse(-N + (i - 1), mod));
                q = Mod(q * i);
                C[i] = Mod(Y[i] * ModInverse(q, mod));
            }
        }

        public long Get(long x)
        {
            if (x <= N) return Y[x];
            long fraq = 1;
            for (int i = 0; i <= N; i++)
                fraq = Mod(fraq * (x - i));
            long res = 0;
            for (int i = 0; i <= N; i++)
            {
                res += Mod(Mod(C[i] * fraq) * ModInverse(x - i, M));
                if (res >= M) res -= M;
            }
            return res;
        }

        long Mod(long x)
        {
            if (x >= M) return x % M;
            else if (x < 0) return (x % M + M);
            else return x;
        }
    }

    static long ModPower(long x, long n, long mod) // x ^ n
    {
        long res = 1;
        while (n > 0)
        {
            if ((n & 1) == 1) res = (res * x) % mod;
            x = (x * x) % mod;
            n >>= 1;
        }
        return res;
    }
    static long ModInverse(long N, long mod)
    {
        long x = 0, y = 0;
        N = (N % mod + mod) % mod;
        ExtGCD(N, mod, ref x, ref y);
        return (x % mod + mod) % mod;
    }
    static long ExtGCD(long a, long b, ref long x, ref long y)
    {
        if (b == 0) { x = 1; y = 0; return a; }
        long res = ExtGCD(b, a % b, ref y, ref x);
        y -= (a / b) * x;
        return res;
    }
}

class Entry { static void Main() { new Program().Solve(); } }
class Reader
{
    private static TextReader reader = Console.In;
    private static readonly char[] separator = { ' ' };
    private static readonly StringSplitOptions op = StringSplitOptions.RemoveEmptyEntries;
    private static string[] A = new string[0];
    private static int i;
    private static void Init() { A = new string[0]; }
    public static void Set(TextReader r) { reader = r; Init(); }
    public static void Set(string file) { reader = new StreamReader(file); Init(); }
    public static bool HasNext() { return CheckNext(); }
    public static string String() { return Next(); }
    public static int Int() { return int.Parse(Next()); }
    public static long Long() { return long.Parse(Next()); }
    public static double Double() { return double.Parse(Next()); }
    public static int[] IntLine() { return Array.ConvertAll(Split(Line()), int.Parse); }
    public static int[] IntArray(int N) { return Enu.Range(0, N).Select(i => Int()).ToArray(); }
    public static int[][] IntTable(int H) { return Enu.Range(0, H).Select(i => IntLine()).ToArray(); }
    public static string[] StringArray(int N) { return Enu.Range(0, N).Select(i => Next()).ToArray(); }
    public static string Line() { return reader.ReadLine().Trim(); }
    private static string[] Split(string s) { return s.Split(separator, op); }
    private static string Next() { CheckNext(); return A[i++]; }
    private static bool CheckNext()
    {
        if (i < A.Length) return true;
        string line = reader.ReadLine();
        if (line == null) return false;
        if (line == "") return CheckNext();
        A = Split(line);
        i = 0;
        return true;
    }
}