import java.io.*;
import java.util.*;

public class Main {
	static final int N=100005;
	static int a[]=new int[N];
	static ArrayList<Integer>G[]=new ArrayList[N];
	static HashMap<ArrayList<Integer>,Integer>vis=new HashMap<ArrayList<Integer>,Integer>();
	static HashMap<String,Integer>book=new HashMap<String,Integer>();
	static int sz;
	static class cmp implements Comparator<Object>{
		@Override
		public int compare(Object o1,Object o2) {
			Integer p1=(Integer)o1;
			Integer p2=(Integer)o2;
			return p1>p2?1:-1;
		}
	}
	static int dfs(int u,int fa) {
		StringBuilder st=new StringBuilder(String.valueOf(u));
		st.append("#");st.append(String.valueOf(fa));
		if(book.containsKey(st.toString())) {
			return book.get(st.toString());
		}
		ArrayList<Integer>temp=new ArrayList<Integer>();
		for(int i=0;i<G[u].size();i++) if(G[u].get(i)!=fa) {
			temp.add(dfs(G[u].get(i),u));
		}
		temp.sort(new cmp());
		if(!vis.containsKey(temp)) {
			vis.put(temp, ++sz);
		}
		book.put(st.toString(),vis.get(temp));
		return vis.get(temp);
	}
	public static void main(String[] args){
		InputReader in = new InputReader(System.in);
	    PrintWriter out = new PrintWriter(System.out);
	    int n=in.nextInt();sz=0;
	    for(int i=0;i<n-1;i++) {
	    	int u=in.nextInt(),v=in.nextInt();
	    	if(G[u]==null) G[u]=new ArrayList<Integer>();
	    	if(G[v]==null) G[v]=new ArrayList<Integer>();
	    	G[u].add(v);G[v].add(u);
	    }
	    int ans=0;
	    HashMap<Integer,Integer>map=new HashMap<Integer,Integer>();
	    for(int i=1;i<=n;i++) {
	    	if(G[i].size()==4) continue;
	    	int id=dfs(i,-1);
	    	if(!map.containsKey(id)) {
	    		ans++;
	    		map.put(id, 1);
	    	}
	    }
	    out.println(ans);
	    out.flush();
	}
	static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;
        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }
        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }
        public int nextInt() {
            return Integer.parseInt(next());
        }
    }
}


import java.io.*;
import java.util.*;
public class Main {
	static final int N=100005;
	static int a[]=new int[N];
	static ArrayList<Integer>G[]=new ArrayList[N];
	static HashMap<ArrayList<Integer>,Integer>vis=new HashMap<ArrayList<Integer>,Integer>();
	static HashMap<StringBuffer,Integer>book=new HashMap<StringBuffer,Integer>();
	static int sz;
	static class cmp implements Comparator<Object>{
		@Override
		public int compare(Object o1,Object o2) {
			Integer p1=(Integer)o1;
			Integer p2=(Integer)o2;
			return p1>p2?1:-1;
		}
	}
	static int dfs(int u,int fa) {
		StringBuffer st=new StringBuffer(u);
		st.append("#");st.append(fa);
		if(book.containsKey(st)) {
			return book.get(st);
		}
		ArrayList<Integer>temp=new ArrayList<Integer>();
		for(int i=0;i<G[u].size();i++) if(G[u].get(i)!=fa) {
			temp.add(dfs(G[u].get(i),u));
		}
		temp.sort(new cmp());
		if(!vis.containsKey(temp)) {
			vis.put(temp, ++sz);
		}
		book.put(st,vis.get(temp));
		return vis.get(temp);
	}
	public static void main(String[] args){
		InputReader in = new InputReader(System.in);
	    PrintWriter out = new PrintWriter(System.out);
	    int n=in.nextInt();sz=0;
	    for(int i=0;i<n-1;i++) {
	    	int u=in.nextInt(),v=in.nextInt();
	    	if(G[u]==null) G[u]=new ArrayList<Integer>();
	    	if(G[v]==null) G[v]=new ArrayList<Integer>();
	    	G[u].add(v);G[v].add(u);
	    }
	    int ans=0;
	    HashMap<Integer,Integer>map=new HashMap<Integer,Integer>();
	    for(int i=1;i<=n;i++) {
	    	if(G[i]==null) continue;
	    	if(G[i].size()==4) continue;
	    	int id=dfs(i,-1);
	    	if(!map.containsKey(id)) {
	    		ans++;
	    		map.put(id, 1);
	    	}
	    }
	    if(n==1) ans=1;
	    out.println(ans);
	    out.flush();
	}
	static class InputReader {
        public BufferedReader reader;
        public StringTokenizer tokenizer;
        public InputReader(InputStream stream) {
            reader = new BufferedReader(new InputStreamReader(stream), 32768);
            tokenizer = null;
        }
        public String next() {
            while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                try {
                    tokenizer = new StringTokenizer(reader.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return tokenizer.nextToken();
        }
        public int nextInt() {
            return Integer.parseInt(next());
        }
    }
}


import java.util.Scanner;
/*
 * !!!!!!!!!!!!!!!!!!!!!!!!!
 * !!!!!!ACTUALLY PrC!!!!!!!
 * !!!!!!!!!!!!!!!!!!!!!!!1!
 */
public class PrD {

	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);

		scan.nextLine();

		boolean cards[][] = new boolean[10][10];

		scan.nextLine();
		String s = scan.nextLine();

		s = s.replaceAll("\\s+", "");
		char c;
		int x;
		for(int i = 0; i < s.length(); i+=2){
			c = s.charAt(i);
			x = Integer.parseInt(String.valueOf(s.charAt(i+1)))-1;
			switch (c){
				case 'R':	cards[0][x] = true;
							break;
				case 'G':	cards[1][x] = true;
							break;
				case 'B':	cards[2][x] = true;
							break;
				case 'Y':	cards[3][x] = true;
							break;
				case 'W':	cards[4][x] = true;
							break;
			}
		}
		int ans = 0;
		int nums = 0, cols = 0;
		for(int i = 0; i < 5; i++){
			for(int j = 0; j < 5; j++){
				if(cards[i][j])
					nums++;

				if(cards[j][i] && i != j)
					cols++;
			}
			if(nums > 0){
				ans += nums-1;
				nums = 0;
			}
			if(cols > 0){
				ans += cols-1;
				cols = 0;
			}
		}
		System.out.println(ans);
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigInteger;

public class BoryaAndHanabi {
    private BoryaAndHanabi() throws IOException {
        BufferedReader rd = new BufferedReader(new InputStreamReader(System.in));
        String h = rd.readLine();
        int n = Integer.parseInt(h);
        h = rd.readLine();
        String[] cards = h.split("\\s+");
        boolean[][] cardExists = new boolean[5][5];
        int[] colorToIndex = new int['Z'];
        colorToIndex['R'] = 0;
        colorToIndex['G'] = 1;
        colorToIndex['B'] = 2;
        colorToIndex['Y'] = 3;
        colorToIndex['W'] = 4;
        for(String c: cards) {
            cardExists[colorToIndex[c.charAt(0)]][c.charAt(1)-'0'] = true;
        }
        int minHints = 10;
        for(int i=0;i<(1<<10);i++) {
            boolean hintsOk = true;
            boolean singleUsed = false;
            for(int j=0;hintsOk && j<5;j++) {
                for(int k=0;hintsOk && k<5;k++) {
                    if(cardExists[j][k]) {
                        boolean colorHint = chint(i, j);
                        boolean digitHint = dhint(i, k);
                        if(!colorHint && !digitHint) {
                            if(singleUsed) {
                                hintsOk = false;
                                break;
                            } else {
                                singleUsed = true;
                            }
                        } else if(colorHint && !digitHint) {
                            for(int m=0;m<5;m++) {
                                if(m != k && cardExists[j][m]) {
                                    if(!dhint(i, m)) {
                                        hintsOk = false;
                                        break;
                                    }
                                }
                            }
                        } else if(!colorHint && digitHint) {
                            for(int m=0;m<5;m++) {
                                if(m != j && cardExists[m][k]) {
                                    if(!chint(i, m)) {
                                        hintsOk = false;
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if(hintsOk) {
                int hints = new BigInteger(i+"").bitCount();
                minHints = Math.min(minHints, hints);
            }
        }
        out(minHints);
    }

    private boolean chint(int i, int x) {
        return (i & (1<<x)) > 0;
    }

    private boolean dhint(int i, int x) {
        return (i & (1<<(x+5))) > 0;
    }

    private static void out(Object x) {
        System.out.println(x);
    }

    public static void main(String[] args) throws IOException {
        new BoryaAndHanabi();
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class A {

    private static final char[] COLOR = {
        'R', 'G', 'B', 'Y', 'W'
    };

    public int solve(int n, String[] cards) {
        int[] c = new int[n];
        for (int i=0; i<n; i++)
            c[i] = convert(cards[i]);
        int res = 10;
        for (int i=0; i<1<<10; i++)
            if (check(n, c, i))
                res = Math.min(res, Integer.bitCount(i));
        return res;
    }

    private int convert(String card) {
        int res = 0;
        for (int i=0; i<COLOR.length; i++)
            if (card.charAt(0)==COLOR[i]) {
                res += i*5;
                break;
            }
        return res + (card.charAt(1)-'1');
    }

    private int possible = 0;

    private boolean check(int n, int[] c, int s) {
        possible = 0;
        int[] rest = new int[25];
        for (int i=0; i<n; i++)
            rest[c[i]]++;
        check(n, c, s, rest, 0);
        return possible==1;
    }

    private void check(int n, int[] c, int s, int[] rest, int idx) {
        if (idx==n) {
            possible++;
            return;
        } else {
            if (possible>=2)
                return;
            int flag = (1<<(c[idx]/5)) | (1<<(5+c[idx]%5));
            if ((flag&s)==flag) {
                if (rest[c[idx]]>0) {
                    rest[c[idx]]--;
                    check(n, c, s, rest, idx+1);
                    rest[c[idx]]++;
                }
            } else if ((flag&s)>=(1<<5)) {
                for (int i=0; i<5; i++)
                    if (rest[i*5+c[idx]%5]>0) {
                        rest[i*5+c[idx]%5]--;
                        check(n, c, s, rest, idx+1);
                        rest[i*5+c[idx]%5]++;
                        if (possible>=2)
                            return;
                    }
            } else if ((flag&s)>0) {
                for (int i=0; i<5; i++)
                    if (rest[(c[idx]/5)*5+i]>0) {
                        rest[(c[idx]/5)*5+i]--;
                        check(n, c, s, rest, idx+1);
                        rest[(c[idx]/5)*5+i]++;
                        if (possible>=2)
                            return;
                    }
            } else {
                for (int i=0; i<25; i++)
                    if (rest[i]>0) {
                        rest[i]--;
                        check(n, c, s, rest, idx+1);
                        rest[i]++;
                        if (possible>=2)
                            return;
                    }
            }
        }
    }

    public static void main(String args[]) throws IOException {
        BufferedReader br = null;
        try {
            br = new BufferedReader(new InputStreamReader(System.in));
            String line = br.readLine();
            int n = Integer.parseInt(line);
            String[] cards = br.readLine().split(" ");
            System.out.println(new A().solve(n, cards));
        } finally {
            if (br!=null)
                br.close();
        }
    }
}


import java.util.*;
import java.io.*;
import java.math.*;
@SuppressWarnings("unchecked")
public class Main {
    InputReader ir = new InputReader(System.in);
    PrintWriter out = new PrintWriter(System.out);
    int colarr[] = new int[5];
    int numarr[] = new int[5];
     HashMap <Character, Integer> map = new HashMap();
    String arr[];
    int n;
    int min = 1000000;
    void solve(){
       n = ir.readInt();
       Set <String> set = new HashSet();
       for(int i = 0; i < n; i++) {
            String str = ir.readString();
            set.add(str);
       }

       map.put('R', 0);
       map.put('G', 1);
       map.put('B', 2);
       map.put('Y', 3);
       map.put('W', 4);
       n = set.size();
       int c = 0;
       arr = new String[n];
       for(String i: set) {
            arr[c++] = i;
            int idx = map.get(i.charAt(0));
            colarr[idx]++;
            idx = (int)(i.charAt(1) - '1');
            numarr[idx]++;
       }

       rec(0,0,0);
       out.println(min);
    }
    void rec(int colmask, int nummask, int count) {
        if(count >= min)
            return;
        //out.println(colmask + " " + nummask);
        boolean visit[] = new boolean[n];
        int tempcol[] = Arrays.copyOf(colarr, 5);
        int tempnum[] = Arrays.copyOf(numarr, 5);
        for(int i = 0; i < n; i++) {

            String str = arr[i];
            int col = map.get(str.charAt(0));
            int num = (int)(str.charAt(1) - '1');
            int mc = 1 << col;
            int mn = 1 << num;

            if(((((mc)&(colmask)) != 0) && (((mn)&(nummask))) != 0)) {

                visit[i] = true;
                tempcol[col]--;
                tempnum[num]--;
            }
        }

        for(int j = 0; j < n; j++)
        for(int i = 0; i < n; i++) {
            if(visit[i] == true)
                continue;
            String str = arr[i];
            int col = map.get(str.charAt(0));
            int num = (int)(str.charAt(1) - '1');
            int mc = 1 << col;
            int mn = 1 << num;
            if(((mc)&(colmask)) != 0) {
                if(tempcol[col] == 1) {
                    visit[i] = true;
                    tempcol[col]--;
                    tempnum[num]--;
                }
            } else if (((mn)&(nummask)) != 0 ) {
                if(tempnum[num] == 1) {
                    visit[i] = true;
                    tempcol[col]--;
                    tempnum[num]--;
                }
            }
        }
        int c = 0;

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

            if(visit[i] == false)
                c++;
        }
        if(c <= 1) {
            min = Math.min(count, count);
        }

        for(int i = 0; i < n; i++) {
            if(((1 << i) & colmask) == 0) {
                rec((1 << i) | colmask, nummask, count + 1);
            }
            if(((1 << i) & nummask) == 0) {
                rec(colmask, (1 << i) | nummask, count + 1);
            }
         }

    }

    void run() {
        solve();
        out.close();
    }
    public static void main(String args[]) {
        new Main().run();
    }
}

class InputReader {

    private InputStream stream;
    private byte[] buf = new byte[1024];
    private int curChar;
    private int numChars;
    private SpaceCharFilter filter;

    public InputReader(InputStream stream) {
        this.stream = stream;
    }

    public int read() {
        if (numChars == -1)
            throw new InputMismatchException();
        if (curChar >= numChars) {
            curChar = 0;
            try {
                numChars = stream.read(buf);
            } catch (IOException e) {
                throw new InputMismatchException();
            }
            if (numChars <= 0)
                return -1;
        }
        return buf[curChar++];
    }
    public final int readInt() {
            int c = read();
            while (isSpaceChar(c))
                c = read();
            int sgn = 1;
            if (c == '-') {
                sgn = -1;
                c = read();
            }
            int res = 0;
            do {
                if (c < '0' || c > '9')
                    throw new InputMismatchException();
                res *= 10;
                res += c - '0';
                c = read();
            } while (!isSpaceChar(c));
            return res * sgn;
    }
    public long readLong() {
        int c = read();
        while (isSpaceChar(c))
            c = read();
        int sgn = 1;
        if (c == '-') {
            sgn = -1;
            c = read();
        }
        long res = 0;
        do {
            if (c < '0' || c > '9')
                throw new InputMismatchException();
            res *= 10;
            res += c - '0';
            c = read();
        } while (!isSpaceChar(c));
        return res * sgn;
    }

    public String readString() {
        int c = read();
        while (isSpaceChar(c))
            c = read();
        StringBuilder res = new StringBuilder();
        do {
            res.appendCodePoint(c);
            c = read();
        } while (!isSpaceChar(c));
        return res.toString();
    }

    public boolean isSpaceChar(int c) {
        if (filter != null)
            return filter.isSpaceChar(c);
        return isWhitespace(c);
    }
        public double readDouble() {
        return Double.parseDouble(readString());
    }

    public static boolean isWhitespace(int c) {
        return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
    }

    public String next() {
        return readString();
    }

    public interface SpaceCharFilter {
        public boolean isSpaceChar(int ch);
    }
}
class Pair <Type1 extends Comparable<Type1>, Type2 extends Comparable<Type2>> implements Comparable <Pair<Type1, Type2>>{
    Type1 first;
    Type2 second;
    public Pair(Type1 F, Type2 S) {
        this.first = F;
        this.second = S;
    }
    @Override
    public int compareTo(Pair <Type1, Type2> p) {
        if(first.compareTo(p.first) == 0)
            return second.compareTo(p.second);
        return first.compareTo(p.first);
    }
}


import java.util.*;
import java.io.*;
public class posperm{
public static int op[] = {0,1,2,4,6,8,9,16,17,18};
public static long dp[][][];
//public static long bf[][];
public static long mod =0;
public static void bf(int pos,int vec,int llevo,int tot,int prop){
if(pos==0){
bf[vec][prop]=(bf[vec][prop]+1)%mod;
return;
}
for(int n = 1;n<=tot;n++){
int prop2 = prop;
if(((1<<n)&llevo)!=0)continue;
if(pos==1){
if(n==tot)prop2|=1;
if(n==tot-1)prop2|=2;
}
if(pos==2){
if(n==tot)prop2|=(1<<2);
if(n==tot-1)prop2|=(1<<3);
if(n==tot-2)prop2|=(1<<4);
}
bf(pos-1,vec+((Math.abs((tot-pos+1)-n)==1)?1:0),llevo|(1<<n),tot,prop2);
}
}
public static long sum(int a,int b,String c[],long voy){
long tal =0;
if(a<0 || a>=dp.length || b<0 || b>=dp.length) return 0;
for(int n= 0;n<c.length;n++)
tal = (tal+dp[a][b][Integer.parseInt(c[n],2)])%mod;
return tal%mod;
}
public static long sum2(int a,int b,String c,long voy){
long tal =0;
if(a<0 || a>=dp.length || b<0 || b>=dp.length) return 0;
int y = 0;
for(int n =0;n<c.length();n++){
if(y>1)return 0;
if(n==3)y =0;
if(c.charAt(n)=='1')y++;
}

int d = c.indexOf("*");
if(d==-1)return dp[a][b][Integer.parseInt(c,2)];
for(int n = 0;n<2;n++)
tal=(tal+sum2(a,b,c.substring(0,d)+n+c.substring(d+1),0))%mod;
return tal%mod;
}
public static void main(String args[]) throws IOException{
BufferedReader lector = new BufferedReader(new InputStreamReader(System.in));
String tmp = lector.readLine();
int a = Integer.parseInt(tmp.substring(0,tmp.indexOf(" ")));
int b = Integer.parseInt(tmp.substring(tmp.indexOf(" ")+1));
mod = 1000000007;
long res = 0;
//bf = new long[Math.max(a+2,4)][33];
dp= new long[Math.max(a+2,4)][Math.max(a+2,4)][33];
dp[1][0][1]=1;
dp[2][0][9]=1;
dp[2][2][6]=1;
dp[3][0][9]=1;
dp[3][0][8]=1;
dp[3][2][6]=1;
dp[3][2][17]=1;
dp[3][2][4]=1;
dp[3][2][18]=1;
String rejoder[] = {"00010","10010","01010","00110"};
String joder[] ={"00000","10000","01000","00100"};
String joder1[] = {"00001","01001","10001"};
String joder2[] = {"00010","10010","00110"};
String joder3[] = {"00000","01000","10000"};
String joder4[] = {"00010","10010"};
for(int n = 4;n<a+1;n++){
for(int m = 0;m<=n;m++){
//dp[n][m][0]=(((m+1)*sum(n-1,m+1,joder,0))%mod+((n-1-m-1)*sum(n-1,m,joder,0))%mod)%mod;
dp[n][m][0]=((m*dp[n-1][m+1][4])%mod+((n-m-2<0?0:n-m-2)*dp[n-1][m][4])%mod+((m+1)*dp[n-1][m+1][8])%mod+
((n-m-3<0?0:n-m-3)*dp[n-1][m][8])%mod +((m+1)*dp[n-1][m+1][16])%mod+((n-m-3<0?0:n-m-3)*dp[n-1][m][16])%mod+
((m+1)*dp[n-1][m+1][0])%mod+((n-m-3<0?0:n-m-3)*dp[n-1][m][0])%mod)%mod;//ta loco
dp[n][m][1]=sum(n-1,m,joder,0)%mod;
dp[n][m][9]=sum(n-1,m,joder1,0)%mod;
dp[n][m][17]=sum(n-1,m,joder2,0)%mod;
dp[n][m][2]=(dp[n-1][m][4]+sum(n-1,m-1,joder3,0))%mod;
//dp[n][m][16]=((m+1)*sum(n-1,m+1,joder2,0)%mod+((n-1-m-1)*sum(n-1,m,joder2,0))%mod)%mod;
dp[n][m][16]=(((m-1<0?0:m-1)*dp[n-1][m+1][6])%mod+((n-m-1<0?0:n-m-1)*dp[n-1][m][6])%mod+(m*dp[n-1][m+1][18])%mod+
((n-m-2<0?0:n-m-2)*dp[n-1][m][18])%mod+(m*dp[n-1][m+1][2])%mod+((n-m-2<0?0:n-m-2)*dp[n-1][m][2])%mod)%mod;//ta loco
dp[n][m][18]=(dp[n-1][m][6]+sum(n-1,m-1,joder4,0))%mod;
dp[n][m][6] = sum(n-1,m-2,joder1,0);
dp[n][m][4] = (sum(n-1,m-1,joder,0)+sum(n-1,m,rejoder,0))%mod;//ta loco
dp[n][m][8] = ((m+1)*sum(n-1,m+1,joder1,0)%mod+((n-1-m-1)*sum(n-1,m,joder1,0))%mod)%mod;
}

}
//bf(a,0,0,a,0);
//long res2 = 0;
for(int k = 0;k<op.length;k++){
//System.out.println(a+" "+b+" "+op[k]+" "+dp[a][b][op[k]]+" "+bf[b][op[k]]);
res=(res+dp[a][b][op[k]])%mod;
//res2 = (res2+bf[b][op[k]])%mod;
}
System.out.println(res%mod);//+" "+res2%mod);
}
}


//package round175;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class E2 {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	void solve()
	{
		int n = ni(), K = ni();
		int mod = 1000000007;
		long[][][][] dp = new long[n][n+1][2][2];
		dp[0][0][0][0] = 1;
		for(int i = 1;i < n;i++){
			for(int j = 0;j <= n;j++){
				dp[i][j][0][0] += dp[i-1][j][0][0];
				dp[i][j][0][0] += dp[i-1][j][0][1];
				dp[i][j][0][0] += dp[i-1][j][1][0];
				dp[i][j][0][0] += dp[i-1][j][1][1];
				dp[i][j][0][0] %= mod;
				if(j-1 >= 0){
					dp[i][j][0][1] += dp[i-1][j-1][0][0];
					dp[i][j][0][1] += dp[i-1][j-1][0][1];
					dp[i][j][1][0] += dp[i-1][j-1][0][0];
					dp[i][j][1][0] += dp[i-1][j-1][1][0];
					dp[i][j][0][1] %= mod;
					dp[i][j][1][0] %= mod;
				}
				if(j-2 >= 0){
					dp[i][j][1][1] += dp[i-1][j-2][0][0];
				}
			}
		}

		int[][] fif = enumFIF(n, mod);

		long[] F = new long[n+1];
		for(int j = 0;j <= n;j++){
			for(int k = 0;k < 2;k++){
				for(int l = 0;l < 2;l++){
					F[j] += dp[n-1][j][k][l];
				}
			}
			F[j] %= mod;
		}

		long ret = 0;
		for(int j = K;j <= n;j++){
			long plus = F[j] * fif[0][n-j] % mod * fif[0][j]%mod*fif[1][j-K]%mod*fif[1][K]%mod;
			if((K-j)%2 == 0){
				ret += plus;
			}else{
				ret += mod-plus;
			}
		}
		out.println(ret%mod);
	}

	public static int[][] enumFIF(int n, int mod)
	{
		int[] f = new int[n+1];
		int[] invf = new int[n+1];
		invf[1] = 1;
		for(int i = 2;i <= n;i++){
			invf[i] = (int)(invf[mod%i]*(long)(mod-mod/i)%mod);
		}

		f[0] = invf[0] = 1;
		for(int i = 1;i <= n;i++){
			f[i] = (int)((long)f[i-1] * i % mod);
			invf[i] = (int)((long)invf[i-1] * invf[i] % mod);
		}
		return new int[][]{f, invf};
	}

	void run() throws Exception
	{
		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new E2().run(); }

	private byte[] inbuf = new byte[1024];
	private int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


import java.util.Arrays;
import java.util.Scanner;

public class E {
    static int n;
    static int[][][] DP;
    static int mod = (int) 1e9 + 7;

    public static int get(int index, int k, int used) {
        if (k < 0)
            return 0;
        if (index == n)
            if (k == 0)
                return 1;
            else
                return 0;
        if (DP[index][k][used] != -1)
            return DP[index][k][used];
        int ans = 0;
        // none
        ans = (ans + get(index + 1, k, (used << 1) & 3)) % mod;
        // i - 1
        if ((used & 2) == 0)
            ans = (ans + get(index + 1, k - 1, (used << 1) & 3)) % mod;
        // i+1
        if (index != n - 1)
            ans = (ans + get(index + 1, k - 1, ((used << 1) & 3) + 1)) % mod;
        return DP[index][k][used] = ans;

    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        n = in.nextInt();
        int k = in.nextInt();
        long[] F = new long[n + 1];
        F[0] = 1;
        for (int i = 1; i <= n; i++)
            F[i] = (F[i - 1] * i) % mod;
        long[][] C = new long[n + 1][n + 1];
        for (int i = 0; i <= n; i++)
            for (int j = 0; j <= i; j++)
                if (j == 0 || i == j)
                    C[i][j] = 1;
                else
                    C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % mod;
        DP = new int[n][n + 1][4];
        for (int i = 0; i < n; i++)
            for (int j = 0; j <= n; j++)
                Arrays.fill(DP[i][j], -1);
        long[] A = new long[n + 1];
        for (int i = 0; i <= n; i++)
            A[i] = (get(0, i, 2) * F[n - i]) % mod;
        for (int i = n - 1; i >= 0; i--)
            for (int j = i + 1; j <= n; j++)
                A[i] = ((A[i] - (C[j][i] * A[j]) % mod) + mod) % mod;
        System.out.println(A[k]);
    }
}


import java.util.*;
import java.io.*;
public class posperm{
public static int op[] = {0,1,2,4,6,8,9,16,17,18};
public static int dp[][][];
//public static long bf[][];
public static int mod =0;
/*public static void bf(int pos,int vec,int llevo,int tot,int prop){
if(pos==0){
bf[vec][prop]=(bf[vec][prop]+1)%mod;
return;
}
for(int n = 1;n<=tot;n++){
int prop2 = prop;
if(((1<<n)&llevo)!=0)continue;
if(pos==1){
if(n==tot)prop2|=1;
if(n==tot-1)prop2|=2;
}
if(pos==2){
if(n==tot)prop2|=(1<<2);
if(n==tot-1)prop2|=(1<<3);
if(n==tot-2)prop2|=(1<<4);
}
bf(pos-1,vec+((Math.abs((tot-pos+1)-n)==1)?1:0),llevo|(1<<n),tot,prop2);
}
}*/
public static int sum(int a,int b,String c[],long voy){
int tal =0;
if(a<0 || a>=dp.length || b<0 || b>=dp.length) return 0;
for(int n= 0;n<c.length;n++)
tal = (tal+dp[a][b][Integer.parseInt(c[n],2)])%mod;
return tal%mod;
}
public static int sum2(int a,int b,String c,long voy){
int tal =0;
if(a<0 || a>=dp.length || b<0 || b>=dp.length) return 0;
int y = 0;
for(int n =0;n<c.length();n++){
if(y>1)return 0;
if(n==3)y =0;
if(c.charAt(n)=='1')y++;
}

int d = c.indexOf("*");
if(d==-1)return dp[a][b][Integer.parseInt(c,2)];
for(int n = 0;n<2;n++)
tal=(tal+sum2(a,b,c.substring(0,d)+n+c.substring(d+1),0))%mod;
return tal%mod;
}
public static void main(String args[]) throws IOException{
BufferedReader lector = new BufferedReader(new InputStreamReader(System.in));
String tmp = lector.readLine();
int a = Integer.parseInt(tmp.substring(0,tmp.indexOf(" ")));
int b = Integer.parseInt(tmp.substring(tmp.indexOf(" ")+1));
mod = 1000000007;
long res = 0;
//bf = new long[Math.max(a+2,4)][33];
dp= new int[Math.max(a+2,4)][Math.max(a+2,4)][33];
dp[1][0][1]=1;
dp[2][0][9]=1;
dp[2][2][6]=1;
dp[3][0][9]=1;
dp[3][0][8]=1;
dp[3][2][6]=1;
dp[3][2][17]=1;
dp[3][2][4]=1;
dp[3][2][18]=1;
String rejoder[] = {"00010","10010","01010","00110"};
String joder[] ={"00000","10000","01000","00100"};
String joder1[] = {"00001","01001","10001"};
String joder2[] = {"00010","10010","00110"};
String joder3[] = {"00000","01000","10000"};
String joder4[] = {"00010","10010"};
for(int n = 4;n<a+1;n++){
for(int m = 0;m<=n;m++){
//dp[n][m][0]=(((m+1)*sum(n-1,m+1,joder,0))%mod+((n-1-m-1)*sum(n-1,m,joder,0))%mod)%mod;
dp[n][m][0]=((m*dp[n-1][m+1][4])%mod+((n-m-2<0?0:n-m-2)*dp[n-1][m][4])%mod+((m+1)*dp[n-1][m+1][8])%mod+
((n-m-3<0?0:n-m-3)*dp[n-1][m][8])%mod +((m+1)*dp[n-1][m+1][16])%mod+((n-m-3<0?0:n-m-3)*dp[n-1][m][16])%mod+
((m+1)*dp[n-1][m+1][0])%mod+((n-m-3<0?0:n-m-3)*dp[n-1][m][0])%mod)%mod;//ta loco
dp[n][m][1]=sum(n-1,m,joder,0)%mod;
dp[n][m][9]=sum(n-1,m,joder1,0)%mod;
dp[n][m][17]=sum(n-1,m,joder2,0)%mod;
dp[n][m][2]=(dp[n-1][m][4]+sum(n-1,m-1,joder3,0))%mod;
//dp[n][m][16]=((m+1)*sum(n-1,m+1,joder2,0)%mod+((n-1-m-1)*sum(n-1,m,joder2,0))%mod)%mod;
dp[n][m][16]=(((m-1<0?0:m-1)*dp[n-1][m+1][6])%mod+((n-m-1<0?0:n-m-1)*dp[n-1][m][6])%mod+(m*dp[n-1][m+1][18])%mod+
((n-m-2<0?0:n-m-2)*dp[n-1][m][18])%mod+(m*dp[n-1][m+1][2])%mod+((n-m-2<0?0:n-m-2)*dp[n-1][m][2])%mod)%mod;//ta loco
dp[n][m][18]=(dp[n-1][m][6]+sum(n-1,m-1,joder4,0))%mod;
dp[n][m][6] = sum(n-1,m-2,joder1,0);
dp[n][m][4] = (sum(n-1,m-1,joder,0)+sum(n-1,m,rejoder,0))%mod;//ta loco
dp[n][m][8] = ((m+1)*sum(n-1,m+1,joder1,0)%mod+((n-1-m-1)*sum(n-1,m,joder1,0))%mod)%mod;
}

}
//bf(a,0,0,a,0);
//long res2 = 0;
for(int k = 0;k<op.length;k++){
//System.out.println(a+" "+b+" "+op[k]+" "+dp[a][b][op[k]]+" "+bf[b][op[k]]);
res=(res+dp[a][b][op[k]])%mod;
//res2 = (res2+bf[b][op[k]])%mod;
}
System.out.println(res%mod);//+" "+res2%mod);
}
}


import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;
import java.util.List;
 import java.util.*;
 public class realfast implements Runnable
  {
    private static final int INF = (int) 1e9;
    long in= (long)Math.pow(10,9)+7;
    long fac[]= new long[3000];
    public  void solve() throws IOException
    {
         long m = in;

       int x = readInt();
       int y = readInt();

       if((y%x)!=0)
        out.println(0);
       else
       {
            int len =y/x;

            int root = (int)Math.pow(len,0.5);
            ArrayList<Integer> arr = new ArrayList<>();
            for(int i =1;i<=root;i++)
            {
                if(len%i==0)
                {
                    int j = len/i;
                    arr.add(i);
                    if(j!=i)
                        arr.add(j);
                }
            }
            Collections.sort(arr);
            long dp[]= new long[arr.size()];
            dp[arr.size()-1]=1;
            for(int i=arr.size()-2;i>=0;i--)
            {
                int yo = arr.get(i);
                dp[i]= pow(2,len/yo-1,in);
                for(int j=i+1;j<arr.size();j++)
                {
                    int sal = arr.get(j);
                    if(sal%yo==0)
                    dp[i]= (dp[i]%in-dp[j]%in+in)%in;
                }
            }
            out.println(dp[0]);
       }

    }
    public int gcd(int a , int b )
    {
      if(a<b)
      {
        int t =a;
        a=b;
        b=t;
      }
      if(a%b==0)
        return b ;
      return gcd(b,a%b);
    }
    public long pow(long n , long p,long m)
    {
         if(p==0)
            return 1;
        long val = pow(n,p/2,m);;
        val= (val*val)%m;
        if(p%2==0)
            return val;
        else
            return (val*n)%m;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    public static void main(String[] args) {
        new Thread(null, new realfast(), "", 128 * (1L << 20)).start();
    }

    private static final boolean ONLINE_JUDGE = System.getProperty("ONLINE_JUDGE") != null;
    private BufferedReader reader;
    private StringTokenizer tokenizer;
    private PrintWriter out;

    @Override
    public void run() {
        try {
            if (ONLINE_JUDGE || !new File("input.txt").exists()) {
                reader = new BufferedReader(new InputStreamReader(System.in));
                out = new PrintWriter(System.out);
            } else {
                reader = new BufferedReader(new FileReader("input.txt"));
                out = new PrintWriter("output.txt");
            }
            solve();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                reader.close();
            } catch (IOException e) {
                // nothing
            }
            out.close();
        }
    }

    private String readString() throws IOException {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            tokenizer = new StringTokenizer(reader.readLine());
        }
        return tokenizer.nextToken();
    }

    @SuppressWarnings("unused")
    private int readInt() throws IOException {
        return Integer.parseInt(readString());
    }

    @SuppressWarnings("unused")
    private long readLong() throws IOException {
        return Long.parseLong(readString());
    }

    @SuppressWarnings("unused")
    private double readDouble() throws IOException {
        return Double.parseDouble(readString());
    }
}
class edge implements Comparable<edge>{
    int val ;
    int color;

    edge(int u, int v)
    {
       this.val=u;
       this.color=v;
    }
    public int compareTo(edge e)
    {
        return this.val-e.val;
    }
}import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;
import java.util.List;
 import java.util.*;
  class realfast implements Runnable
  {
    private static final int INF = (int) 1e9;
    long in= (long)Math.pow(10,9)+7;
    long fac[]= new long[3000];
    public  void solve() throws IOException
    {
         long m = in;

       int x = readInt();
       int y = readInt();

       if((y%x)!=0)
        out.println(0);
       else
       {
            int len =y/x;

            int root = (int)Math.pow(len,0.5);
            ArrayList<Integer> arr = new ArrayList<>();
            for(int i =1;i<=root;i++)
            {
                if(len%i==0)
                {
                    int j = len/i;
                    arr.add(i);
                    if(j!=i)
                        arr.add(j);
                }
            }
            Collections.sort(arr);
            long dp[]= new long[arr.size()];
            dp[arr.size()-1]=1;
            for(int i=arr.size()-2;i>=0;i--)
            {
                int yo = arr.get(i);
                dp[i]= pow(2,len/yo-1,in);
                for(int j=i+1;j<arr.size();j++)
                {
                    int sal = arr.get(j);
                    if(sal%yo==0)
                    dp[i]= (dp[i]%in-dp[j]%in+in)%in;
                }
            }
            out.println(dp[0]);
       }

    }
    public int gcd(int a , int b )
    {
      if(a<b)
      {
        int t =a;
        a=b;
        b=t;
      }
      if(a%b==0)
        return b ;
      return gcd(b,a%b);
    }
    public long pow(long n , long p,long m)
    {
         if(p==0)
            return 1;
        long val = pow(n,p/2,m);;
        val= (val*val)%m;
        if(p%2==0)
            return val;
        else
            return (val*n)%m;
    }

    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    public static void main(String[] args) {
        new Thread(null, new realfast(), "", 128 * (1L << 20)).start();
    }

    private static final boolean ONLINE_JUDGE = System.getProperty("ONLINE_JUDGE") != null;
    private BufferedReader reader;
    private StringTokenizer tokenizer;
    private PrintWriter out;

    @Override
    public void run() {
        try {
            if (ONLINE_JUDGE || !new File("input.txt").exists()) {
                reader = new BufferedReader(new InputStreamReader(System.in));
                out = new PrintWriter(System.out);
            } else {
                reader = new BufferedReader(new FileReader("input.txt"));
                out = new PrintWriter("output.txt");
            }
            solve();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                reader.close();
            } catch (IOException e) {
                // nothing
            }
            out.close();
        }
    }

    private String readString() throws IOException {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            tokenizer = new StringTokenizer(reader.readLine());
        }
        return tokenizer.nextToken();
    }

    @SuppressWarnings("unused")
    private int readInt() throws IOException {
        return Integer.parseInt(readString());
    }

    @SuppressWarnings("unused")
    private long readLong() throws IOException {
        return Long.parseLong(readString());
    }

    @SuppressWarnings("unused")
    private double readDouble() throws IOException {
        return Double.parseDouble(readString());
    }
}
class edge implements Comparable<edge>{
    int val ;
    int color;

    edge(int u, int v)
    {
       this.val=u;
       this.color=v;
    }
    public int compareTo(edge e)
    {
        return this.val-e.val;
    }
}


import java.util.*;

import java.util.Collections;
import java.util.ArrayList;

public class javaapplication1 {

    public static final int MAX = 1000000007;

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);

        ArrayList<Integer> Dividendos = new ArrayList<>();

        int intX = in.nextInt();
        //long longX = (long)intX;
        int intY = in.nextInt();
        //long longY = (long)intY;

        //int[] arrDividendos = new int[intX];

        //No en Comun
        if (intY % intX != 0) {
            System.out.println(0);
        }else{
            intY = intY / intX;

        for (long i = 2; i * i <= intY; i++) {
            //Iniciar si es par
            if (intY % i == 0) {
                Dividendos.add((int) i);
            }
            //Es par pero no es el mismo numero
            if (intY % i == 0 && (intY / i != i)) {
                Dividendos.add(intY / (int) i);
            }
            /*
             if(intY % i == 0 && i !=intX){
                Dividendos.add(intY /x);
            }*/
        }

        if (intY != 1) {
            Dividendos.add(intY);
        } else {
            System.out.println(1);
            return;
        }

        int[] arrAnswer = new int[Dividendos.size()];
        long total = 0;
        Collections.sort(Dividendos);
        int temp = 0;
        for (int i = 0; i < arrAnswer.length; i++) {
            temp = (MAX + potencia(2, Dividendos.get(i) - 1,arrAnswer) - 1);
            //if(temp > intX){
            arrAnswer[i] = temp % MAX;
            //}
        }

        for (int i = 1; i < arrAnswer.length; i++) {
            for (int j = i - 1; j >= 0; j--) {
                if (Dividendos.get(i) % Dividendos.get(j) == 0) {
                    temp =(int) ((MAX + arrAnswer[i] - (long) arrAnswer[j])
                    arrAnswer[i] = temp % MAX);
                }
                 /*
                    if(intY % i == 0 && i !=intX){
                    Dividendos.add(intY /x);
                    }*/
            }
            total += arrAnswer[i];
            total = total % MAX;
        }
        System.out.println(arrAnswer[Dividendos.size() - 1]);
        }
    }

    public static int potencia(long x1, int x2, int[] intanswer) {
        long longI = 1;
        while (x2 >= 1) {
            if (x2 % 2 == 1) {
                longI = (longI * x1) % MAX;
            }
            x1 = (x1 * x1) % MAX;
            x2 = x2 /2;

        }
        //else
       //{break;
               // }
        return (int) longI;
    }

}


import static java.util.Arrays.*;
import static java.lang.Math.*;
import static java.math.BigInteger.*;
import java.util.*;
import java.math.*;
import java.io.*;

public class Main implements Runnable {

	boolean TEST = System.getProperty("ONLINE_JUDGE") == null;

    void solve() throws IOException {
    	int x = nextInt(), y = nextInt();
    	if (y % x != 0) {
    		out.println(0);
    		return;
    	}
    	out.println(f(y / x));
    }

    int MOD = (int)1e9 + 7;
    long f(int t) {
    	if (t == 1) return 1;
    	long res = pow(2, t - 1, MOD);
    	for (int i = 2; i * i <= t; i++)
    		if (t % i == 0) {
    			res = (res + MOD - f(i)) % MOD;
    			if (i * i != t) res = (res + MOD - f(t / i)) % MOD;
    		}
    	return (res + MOD - 1) % MOD;
    }

    long pow(long a, long p, int MOD) {
    	if (p == 0) return 1;
    	long b = pow(a, p / 2, MOD);
    	if (p % 2 == 0) return b * b % MOD;
    	return b * b % MOD * a % MOD;
    }

    String next() throws IOException {
        while(st == null || !st.hasMoreTokens()) st = new StringTokenizer(input.readLine());
        return st.nextToken();
    }

    int nextInt() throws IOException {
        return Integer.parseInt(next());
    }

    long nextLong() throws IOException {
        return Long.parseLong(next());
    }

    double nextDouble() throws IOException {
        return Double.parseDouble(next());
    }

    void debug(Object... o) {
        System.out.println(deepToString(o));
    }

    void gcj(Object o) {
        String s = String.valueOf(o);
        out.println("Case #" + test + ": " + s);
        System.out.println("Case #" + test + ": " + s);
    }

    BufferedReader input;
    PrintWriter out;
    StringTokenizer st;
    int test;

    void init() throws IOException {
        if (TEST) input = new BufferedReader(new FileReader("input.in"));
        else input = new BufferedReader(new InputStreamReader(System.in));
        out = new PrintWriter(new BufferedOutputStream(System.out));
    }

    public static void main(String[] args) throws IOException {
        new Thread(null, new Main(), "", 1 << 20).start();
    }

    public void run() {
        try {
            init();
            if (TEST) {
                int runs = nextInt();
                for(int i = 0; i < runs; i++) solve();
            } else solve();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }
}


import java.util.*;
import java.io.*;

public class Main {
	public static void main(String args[]) {new Main().run();}

	FastReader in = new FastReader();
	PrintWriter out = new PrintWriter(System.out);
	void run(){
		work();
		out.flush();
	}
	long mod=1000000007;
	long gcd(long a,long b) {
		return a==0?b:b>=a?gcd(b%a,a):gcd(b,a);
	}
	ArrayList<Integer> rec=new ArrayList<>();
	void work() {
		int a=in.nextInt(),b=in.nextInt();
		if(b%a!=0) {
			out.println(0);
			return;
		}
		b/=a;
		if(b==1) {
			out.println(1);
			return;
		}
		for(int i=2;i*i<=b;i++) {
			if(b%i==0) {
				rec.add(i);
				if(i!=b/i)rec.add(b/i);
			}
		}
		out.println(find(b));
	}
	private long find(int b) {
		long r=(pow(2,b-1)-1+mod)%mod;
		for(int k:rec) {
			if(b%k==0) {
				r-=find(b/k);
				r=(r+mod)%mod;
			}
		}
		return r;
	}
	private long pow(long a, long b) {
		long r=1;
		while(b>0) {
			if(b%2==1) {
				r*=a;
				r%=mod;
			}
			b/=2;
			a*=a;
			a%=mod;
		}
		return r;
	}
}

class FastReader
{
	BufferedReader br;
	StringTokenizer st;

	public FastReader()
	{
		br=new BufferedReader(new InputStreamReader(System.in));
	}

	public String next()
	{
		if(st==null || !st.hasMoreElements())
		{
			try {
				st = new StringTokenizer(br.readLine());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return st.nextToken();
	}

	public int nextInt()
	{
		return Integer.parseInt(next());
	}

	public long nextLong()
	{
		return Long.parseLong(next());
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.StringTokenizer;

public class d {
    static double EPS = 1e-7;
    public static void main(String[] args) {
        FS in = new FS(System.in);
        PrintWriter out = new PrintWriter(System.out);

        int n = in.nextInt();

        Vec com = new Vec(0, 0);
        Vec[] vecs = new Vec[n];
        for(int i = 0; i < n; i++) {
            com = com.add(vecs[i] = new Vec(in.nextInt(), in.nextInt()));
        }
        com = com.scale(1.0/n);

        boolean[] works = new boolean[n];
        Arrays.fill(works, true);
        int num = n;
        for(int i = 0; i < n; i++) {
            if(vecs[i].equals(com)) {
                works[i] = false;
                num--;
                continue;
            }
            for(int j = 0; j < i; j++) {
                if(vecs[i].sub(com).equals(com.sub(vecs[j]))) {
                    works[i] = works[j] = false;
                    num -= 2;
                    break;
                }
            }
        }
        Vec[] act = new Vec[num];
        int curr = 0;
        for(int i = 0; i < n; i++) if(works[i]) act[curr++] = vecs[i];
        n = num;
        if(n == 0) {
            System.out.println(-1);
            return;
        }
        int res = 0;

        Vec[] norms = new Vec[n];

        outer: for(int i = 0; i < n; i++) {
            Vec diff = act[i].sub(act[0]);
            Vec mid = act[0].add(diff.scale(0.5));
            Vec perp = com.sub(mid);
            Vec norm = perp.rot90();
            norm = norm.scale(1.0/Math.sqrt(norm.dot(norm)));
            if(norm.x < 0) {
                norm.x *= -1;
                norm.y *= -1;
            }
            norms[i] = norm;
            for(int j = 0; j < i; j++) {
                if(norms[j].equals(norm)) continue outer;
            }
            double[] arr = new double[n];
            for(int j = 0; j < n; j++) arr[j] = norm.dot(act[j]);
            Arrays.sort(arr);
            double cent = norm.dot(com);
            for(int j = 0; j < n; j++) {
                if(!eq(cent-arr[j], arr[n-1-j]-cent)) continue outer;
            }
            res++;
        }
        System.out.println(res);
        out.close();
    }

    static class Vec {
        double x, y;

        public Vec(double A, double B) {
            x = A;
            y = B;
        }

        public Vec add(Vec o) {
            return new Vec(x+o.x, y+o.y);
        }

        public Vec sub(Vec o) {
            return new Vec(x-o.x, y-o.y);
        }

        public Vec scale(double s) {
            return new Vec(x*s, y*s);
        }

        public Vec rot90() {
            return new Vec(-y, x);
        }

        public double dot(Vec o) {
            return x*o.x + y*o.y;
        }

        @Override
        public boolean equals(Object o) {
            return eq(x, ((Vec)o).x) && eq(y, ((Vec)o).y);
        }
    }

    static boolean eq(double a, double b) {
        return Math.abs(a-b) <= EPS;
    }

    static class FS {
        BufferedReader in;
        StringTokenizer token;

        public FS(InputStream str) {
            in = new BufferedReader(new InputStreamReader(str));
        }

        public String next() {
            if(token == null || !token.hasMoreElements()) {
                try {
                    token = new StringTokenizer(in.readLine());
                } catch (IOException ex) {
                }
                return next();
            }
            return token.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.StringTokenizer;

public class d {
    static double EPS = 1e-6;
    public static void main(String[] args) {
        FS in = new FS(System.in);
        PrintWriter out = new PrintWriter(System.out);

        int n = in.nextInt();

        Vec com = new Vec(0, 0);
        Vec[] vecs = new Vec[n];
        for(int i = 0; i < n; i++) {
            com = com.add(vecs[i] = new Vec(in.nextInt(), in.nextInt()));
        }
        com = com.scaleR(n);

        boolean[] works = new boolean[n];
        Arrays.fill(works, true);
        int num = n;
        for(int i = 0; i < n; i++) {
            if(vecs[i].equals(com)) {
                works[i] = false;
                num--;
                continue;
            }
            for(int j = 0; j < i; j++) {
                if(works[j] && vecs[i].sub(com).equals(com.sub(vecs[j]))) {
                    works[i] = works[j] = false;
                    num -= 2;
                    break;
                }
            }
        }
        Vec[] act = new Vec[num];
        int curr = 0;
        for(int i = 0; i < n; i++) if(works[i]) act[curr++] = vecs[i];
        n = num;
        if(n == 0) {
            System.out.println(-1);
            return;
        }
        int res = 0;

        Vec[] norms = new Vec[n];

        outer: for(int i = 0; i < n; i++) {
            Vec diff = act[i].sub(act[0]);
            Vec mid = act[0].add(diff.scaleR(2));
            Vec perp = com.sub(mid);
            Vec norm = perp.rot90();
            norm = norm.scaleR(Math.sqrt(norm.dot(norm)));
            if(norm.x < 0) {
                norm.x *= -1;
                norm.y *= -1;
            }
            norms[i] = norm;
            for(int j = 0; j < i; j++) {
                if(norms[j].equals(norm)) continue outer;
            }
            double[] arr = new double[n];
            for(int j = 0; j < n; j++) arr[j] = norm.dot(act[j]);
            Arrays.sort(arr);
            double cent = (arr[0]+arr[n-1])/2;
            for(int j = 0; j < n; j++) {
                if(!eq(cent-arr[j], arr[n-1-j]-cent)) continue outer;
            }
            res++;
        }
        System.out.println(res);
        out.close();
    }

    static class Vec {
        double x, y;

        public Vec(double A, double B) {
            x = A;
            y = B;
        }

        public Vec add(Vec o) {
            return new Vec(x+o.x, y+o.y);
        }

        public Vec sub(Vec o) {
            return new Vec(x-o.x, y-o.y);
        }

        public Vec scale(double s) {
            return new Vec(x*s, y*s);
        }

        public Vec scaleR(double s) {
            return new Vec(x/s, y/s);
        }

        public Vec rot90() {
            return new Vec(-y, x);
        }

        public double dot(Vec o) {
            return x*o.x + y*o.y;
        }

        @Override
        public boolean equals(Object o) {
            return eq(x, ((Vec)o).x) && eq(y, ((Vec)o).y);
        }
    }

    static boolean eq(double a, double b) {
        return Math.abs(a-b) <= EPS;
    }

    static class FS {
        BufferedReader in;
        StringTokenizer token;

        public FS(InputStream str) {
            in = new BufferedReader(new InputStreamReader(str));
        }

        public String next() {
            if(token == null || !token.hasMoreElements()) {
                try {
                    token = new StringTokenizer(in.readLine());
                } catch (IOException ex) {
                }
                return next();
            }
            return token.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }
    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeSet;

public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        Scanner in = new Scanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskD {
        public void solve(int testNumber, Scanner in, PrintWriter out) {
            int n = in.nextInt();
            Point[] p = new Point[n];
            Point cen = new Point(0, 0);
            for (int i = 0; i < n; i++) {
                long x = in.nextLong();
                long y = in.nextLong();
                p[i] = new Point(x, y);
                cen = cen.add(p[i]);
                p[i] = p[i].mul(n);
            }
            for (int i = 0; i < n; ++i) {
                p[i] = p[i].minus(cen);
            }
            p = removeSymmetrical(p);
            n = p.length;
            if (n == 0) {
                out.println("-1");
                return;
            }
            Set<Point> ans = new TreeSet<>();
            for (int i = 0; i < n; ++i) {
                Point a = p[0], b = p[i];
                Point vec = a.add(b).rotate90();
                vec.normalizeDirection();
                long[] d = new long[n];
                for (int j = 0; j < n; ++j)
                    d[j] = dot(p[j], vec);

                Arrays.sort(d);
                boolean ok = true;
                for (int j = 0; j < n; ++j) {
                    if (d[j] + d[n - j - 1] != 0) {
                        ok = false;
                        break;
                    }
                }
                if (ok) ans.add(vec);
            }
            out.println(ans.size());
        }

        private Point[] removeSymmetrical(Point[] p) {
            int n = p.length;
            boolean[] dead = new boolean[n];
            for (int i = 0; i < n; i++) {
                for (int j = i + 1; j < n; j++) {
                    if (!dead[i] && !dead[j] && p[i].x == -p[j].x && p[i].y == -p[j].y) {
                        dead[i] = true;
                        dead[j] = true;
                    }
                }
            }
            int k = 0;
            for (int i = 0; i < n; i++) {
                if (!dead[i] || p[i].x == 0 && p[i].y == 0) {
                    p[k++] = p[i];
                }
            }
            return Arrays.copyOf(p, k);
        }

        private long dot(Point a, Point b) {
            return a.x * b.x + a.y * b.y;
        }

        private long gcd(long a, long b) {
            return b == 0 ? a : gcd(b, a % b);
        }

        class Point implements Comparable<Point> {
            long x;
            long y;

            Point(long x, long y) {
                this.x = x;
                this.y = y;
            }

            Point add(Point o) {
                return new Point(x + o.x, y + o.y);
            }

            Point minus(Point o) {
                return new Point(x - o.x, y - o.y);
            }

            Point mul(long n) {
                return new Point(x * n, y * n);
            }

            Point rotate90() {
                return new Point(-y, x);
            }

            void normalizeDirection() {
                long d = gcd(Math.abs(x), Math.abs(y));
                if (y > 0 || y == 0 && x > 0) {

                } else {
                    x = -x;
                    y = -y;
                }
                if (d != 0) {
                    x /= d;
                    y /= d;
                }
            }

            public int compareTo(Point o) {
                if (x != o.x) {
                    return x < o.x ? -1 : 1;
                }
                if (y != o.y) {
                    return y < o.y ? -1 : 1;
                }
                return 0;
            }

        }

    }
}


import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Set;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.TreeSet;
import java.util.StringTokenizer;
import java.io.BufferedReader;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        FastScanner in = new FastScanner(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskD solver = new TaskD();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskD {
        public void solve(int testNumber, FastScanner in, PrintWriter out) {
            int n = in.nextInt();
            Point[] p = new Point[n];
            long sx = 0;
            long sy = 0;
            for (int i = 0; i < n; i++) {
                long x = in.nextLong();
                long y = in.nextLong();
                x *= n;
                y *= n;
                p[i] = new Point(x, y);
                sx += x;
                sy += y;
            }
            sx /= n;
            sy /= n;
            for (int i = 0; i < n; i++) {
                p[i].x -= sx;
                p[i].y -= sy;
            }
            p = removeSymmetrical(p);
            n = p.length;

            if (n <= 1) {
                out.println(-1);
                return;
            }

            Set<Point> ans = new TreeSet<>();
            for (int i = 0; i < n; i++) {
                Point dir = p[0].add(p[i]).rotate90();
                dir.normalizeDirection();
                long[] xs = new long[n];
                for (int j = 0; j < n; j++) {
                    xs[j] = dot(dir, p[j]);
                }
                Arrays.sort(xs);

                boolean ok = true;
                for (int j = 0; j < n; j++) {
                    if (xs[0] + xs[n - 1] != xs[j] + xs[n - 1 - j]) {
                        ok = false;
                        break;
                    }
                }
                if (ok) {
                    ans.add(dir);
                }
            }
            out.println(ans.size());
        }

        private Point[] removeSymmetrical(Point[] p) {
            int n = p.length;
            boolean[] dead = new boolean[n];
            for (int i = 0; i < n; i++) {
                for (int j = i + 1; j < n; j++) {
                    if (!dead[i] && !dead[j] && p[i].x == -p[j].x && p[i].y == -p[j].y) {
                        dead[i] = true;
                        dead[j] = true;
                    }
                }
            }

            int k = 0;
            for (int i = 0; i < n; i++) {
                if (!dead[i]) {
                    p[k++] = p[i];
                }
            }
            return Arrays.copyOf(p, k);
        }

        private long dot(Point a, Point b) {
            return a.x * b.x + a.y * b.y;
        }

        private long gcd(long a, long b) {
            return b == 0 ? a : gcd(b, a % b);
        }

        class Point implements Comparable<Point> {
            long x;
            long y;

            Point(long x, long y) {
                this.x = x;
                this.y = y;
            }

            Point add(Point o) {
                return new Point(x + o.x, y + o.y);
            }

            Point rotate90() {
                return new Point(-y, x);
            }

            void normalizeDirection() {
                long d = gcd(Math.abs(x), Math.abs(y));
                if (y > 0 || y == 0 && x > 0) {

                } else {
                    x = -x;
                    y = -y;
                }
                x /= d;
                y /= d;
            }

            public int compareTo(Point o) {
                if (x != o.x) {
                    return x < o.x ? -1 : 1;
                }
                if (y != o.y) {
                    return y < o.y ? -1 : 1;
                }
                return 0;
            }

        }

    }

    static class FastScanner {
        private BufferedReader in;
        private StringTokenizer st;

        public FastScanner(InputStream stream) {
            in = new BufferedReader(new InputStreamReader(stream));
        }

        public String next() {
            while (st == null || !st.hasMoreTokens()) {
                try {
                    st = new StringTokenizer(in.readLine());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return st.nextToken();
        }

        public int nextInt() {
            return Integer.parseInt(next());
        }

        public long nextLong() {
            return Long.parseLong(next());
        }

    }
}


//import java.awt.Dimension;
import java.awt.Point;
import java.io.*;
import static java.lang.Math.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import static java.math.BigInteger.*;
import java.util.*;
import static java.util.Arrays.*;
//import java.math.BigInteger;
//import static java.lang.Character.*;
//import static java.lang.Math.*;
//import static java.math.BigInteger.*;

//import static java.util.Arrays.*;

//import java.awt.Point; // interger !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//import java.awt.Polygon;
//import java.awt.Rectangle;
//import java.awt.geom.AffineTransform;
//import java.awt.geom.Line2D;
//import java.awt.geom.Point2D;
//import javafx.scene.shape.Line;
//import javafx.scene.transform.Rotate;

//<editor-fold defaultstate="collapsed" desc="Main">
public class Main implements Runnable{

    // https://netbeans.org/kb/73/java/editor-codereference_ru.html#display

    static boolean oj;

    @Override
    public void run(){
        try {
            Locale.setDefault(Locale.US);
        } catch (Exception e) {
        }
        oj = true;
        try {
            oj = System.getProperty("MYLOCAL") == null;
        } catch (Exception e) {
        }
//
        if (oj) {
            sc = new FastScanner(new InputStreamReader(System.in));
            out = new PrintWriter(new OutputStreamWriter(System.out));
        } else {
            try {
                sc = new FastScanner(new FileReader("input.txt"));
                out = new PrintWriter(new FileWriter("output.txt"));
            } catch (IOException e) {
                MLE();
            }
        }
        Solver s = new Solver();
        s.sc = sc;
        s.out = out;

        s.solve();
        if (!oj) {
            err.println("Time: " + (System.currentTimeMillis() - timeBegin) / 1e3);
            err.printf("Mem: %d\n", (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) >> 20);
        }
        out.flush();
    }

    private void show(int[] arr) {
        for (int v : arr) {
            err.print(" " + v);
        }
        err.println();
    }

    public static void exit() {
        err.println("Time: " + (System.currentTimeMillis() - timeBegin) / 1e3);
        err.printf("Mem: %d\n", (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) >> 20);
        out.flush();
        out.close();
        System.exit(0);
    }

    public static void MLE() {
        int[][] arr = new int[1024 * 1024][];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = new int[1024 * 1024];
        }
    }

    public static void main(String[] args) throws FileNotFoundException {
        //new Main().run();
        new Thread(null, new Main(), "myThread", 100 * 1024 * 1024).start();
    }

    static long timeBegin = System.currentTimeMillis();
    static FastScanner sc;
    static PrintWriter out;
    static PrintStream err = System.err;
}
    //</editor-fold>

//<editor-fold defaultstate="collapsed" desc="FastScanner">
class FastScanner {

    BufferedReader br;
    StringTokenizer st;

    FastScanner(InputStreamReader reader) {
        br = new BufferedReader(reader);
        st = new StringTokenizer("");
    }

    String next() {
        while (!st.hasMoreElements()) {
            try {
                st = new StringTokenizer(br.readLine());
            } catch (Exception ex) {
                return null;
            }
        }
        return st.nextToken();
    }

    int nextInt() {
        return Integer.parseInt(next());
    }

    long nextLong() {
        return Long.parseLong(next());
    }

    double nextDouble() {
        return Double.parseDouble(next());
    }

    String nextLine() {
        try {
            return br.readLine();
        } catch (IOException ex) {
            return null;
        }
    }
}
//</editor-fold>

class Solver {

    void aser(boolean OK) {
        if (!OK) {
            Main.MLE();
        }
    }

    FastScanner sc;
    PrintWriter out;
    static PrintStream err = System.err;

    long[] getAllDiv(long A){
        TreeSet<Long> arr = new TreeSet<>();
        for( long d = 1; d*d <= A; ++d ){
            if( A % d == 0 ) {
                arr.add(d);
                arr.add(A/d);
            }
        }
        int pos = 0;
        long[] a = new long[arr.size()];
        for (long x : arr) a[pos++] = x;
        return a;
    }

    long myPow(long p, int alfa){
        long ans = 1;
        for (int i = 0; i < alfa; i++) {
            ans *= p;
        }
        return ans;
    }

    void solve(){
        final long A = sc.nextLong();
        long[] divA = getAllDiv(A);
        TreeMap<Long,TreeSet<Integer>> P = new TreeMap<>();
        for (long div : divA) {
            --div;
            for (int alfa = 1; alfa <= 60; alfa++) {
                long p = (long)( pow( div, 1.0 / alfa ) + 0.5 );
                if( 2<=p && myPow(p,alfa)==div &&
                        valueOf(p).isProbablePrime(Integer.MAX_VALUE) ){
                    if( !P.containsKey(p) )
                        P.put(p, new TreeSet<>());
                    P.get(p).add(alfa);

                }
            }
        }

        long[] dp0, dp;
        dp0 = new long[divA.length];
        dp0[0] = 1;
        for( long p : P.keySet() ){
            dp = dp0.clone();
            for( int alfa : P.get(p) ){
                long val = myPow(p, alfa) + 1;
                for( int ID = 0; ID < divA.length; ++ID){
                    long div = divA[ID];
                    if( 1e12 + 5 <= 1.0 * div * val ) break;
                    long toDiv = div * val;
                    int toID = binarySearch(divA, toDiv);
                    if( 0 <= toID ) dp[toID] += dp0[ID];
                }
            }
            //
            dp0 = dp;
        }
        out.println(dp0[divA.length - 1]);
    }

}


import java.io.*;
import java.lang.Math;
import java.util.*;

public class Main
{
	public BufferedReader in;
	public PrintStream out;

	public boolean log_enabled = false;

	static long[] primes;
	static int p_count;

	public static void get_primes(int n)
	{
		primes = new long[80000];

		boolean[] v = new boolean[n+1];
		int i,j;
		for (i=2; i<=n;i++)
		{
			v[i] = true;
		}

		for (i=2; i*i<=n;i++)
		{
			if (v[i])
			{
				for (j=i; i*j<=n; j++)
				{
					v[i*j]=false;
				}
			}
		}

		p_count = 0;
		for (i=2; i<=n; i++)
		{
			if (v[i])
			{
				primes[p_count++] = i;
			}
		}
	}

	int d_count;
	int[] d_index;
	long A;

	public int d_index(long x)
	{
		if ( (x<1000000) && (x*x<=A))
		{
			return d_index[(int)x];
		}
		else
		{
			return d_count - d_index[(int)(A/x)] - 1;
		}
	}

	public void test()
	{
		A = readLong();

		if (A==1)
		{
			out.println(1);
			return;
		}

		get_primes(1000000);

		long[] dividers = new long[10000];
		d_count = 0;

		d_index = new int[1000001];

		long[] use_primes = new long[10000];
		int use_p_count = 0;

		boolean[] p_used = new boolean[1000000];
		Arrays.fill(p_used, false);

		int i;
		long I;
		for (I=1; I*I<=A; I++)
		{
			if (A % I == 0)
			{
				d_index[(int)I] = d_count;
				dividers[d_count++] = I;
			}
		}

		for (i=0; i<d_count; i++)
		{
			dividers[2*d_count-i-1] = A / dividers[i];
		}

		d_count *= 2;

		long d;
		int p;
		boolean is_prime;

		for (i=1; i<d_count; i++)
		{
			is_prime = true;
			d = dividers[i]-1;

			if (d==1) continue;

			for ( p=0; p<p_count; p++)
			{
				if (primes[p]*primes[p] > d)
				{
					break;
				}

				if (d % primes[p] == 0)
				{
					is_prime = false;
					while (d % primes[p] == 0)
					{
						d /= primes[p];
					}
					if (d==1)
					{
						if (!p_used[(int)primes[p]])
						{
							p_used[(int)primes[p]] = true;
							use_primes[use_p_count++] = primes[p];
						}
					}
				}
			}

			if (is_prime)
			{
				if ((d > 1000000) || !p_used[(int)d])
				{
					if (d<1000000)
					{
						p_used[(int)d] = true;
					}
					use_primes[use_p_count++] = d;
				}
			}
		}

		logWrite("use_p_count = %d\n", use_p_count);

		long[] D = new long[d_count];
		long[] D1 = new long[d_count];

		Arrays.fill(D, 0);
		D[0] = 1;

		for (p=0; p<use_p_count; p++)
		{
			logWrite("P = %d\n", use_primes[p]);
			for (i=1; i<d_count; i++)
			{
				D1[i] = D[i];
				d = use_primes[p];
				while (d<dividers[i])
				{
					if (dividers[i] % (d+1) == 0)
					{

						//logWrite("D1[%d] += D[%d] = %d + %d  \n", i,  d_index(dividers[i] / (d+1)), D1[i], D[d_index(dividers[i] / (d+1))]);

						D1[i] += D[d_index(dividers[i] / (d+1))];
					}

					d *= use_primes[p];
				}
			}

			for (i=1; i<d_count; i++) D[i] = D1[i];
		}

		out.println(D[d_count-1]);
	}

	public void run()
	{
		try
		{
			in = new BufferedReader(new InputStreamReader(System.in));
			out = System.out;

			//in = new BufferedReader(new FileReader("in.txt"));
			//out = new PrintStream(new File("out.txt"));

		}
		catch (Exception e)
		{
			return;
		}

		//while (true)
		{
			//int t = readInt(); for (int i=0; i<t; i++)
			{
				test();
			}
		}
	}

	public static void main(String args[])
	{
		new Main().run();
	}

	private StringTokenizer tokenizer = null;

	public int readInt()
	{
        return Integer.parseInt(readToken());
    }

    public long readLong()
	{
        return Long.parseLong(readToken());
    }

    public double readDouble()
	{
        return Double.parseDouble(readToken());
    }

	public String readLn()
	{
		try
		{
			String s;
			while ((s = in.readLine()).length()==0);
			return s;
		}
		catch (Exception e)
		{
			return "";
		}
	}

    public String readToken()
	{
		try
		{
			while (tokenizer == null || !tokenizer.hasMoreTokens())
			{
				tokenizer = new StringTokenizer(in.readLine());
			}
			return tokenizer.nextToken();
		}
		catch (Exception e)
		{
			return "";
		}
    }

	public int[] readIntArray(int n)
	{
		int[] x = new int[n];
		readIntArray(x, n);
		return x;
	}

	public void readIntArray(int[] x, int n)
	{
		for (int i=0; i<n; i++)
		{
			x[i] = readInt();
		}
	}

	public void logWrite(String format, Object... args)
	{
		if (!log_enabled)
		{
			return;
		}

		out.printf(format, args);
	}
}


//import java.awt.Dimension;
import java.awt.Point;
import java.io.*;
import static java.lang.Math.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import static java.math.BigInteger.*;
import java.util.*;
import static java.util.Arrays.*;
//import java.math.BigInteger;
//import static java.lang.Character.*;
//import static java.lang.Math.*;
//import static java.math.BigInteger.*;

//import static java.util.Arrays.*;

//import java.awt.Point; // interger !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//import java.awt.Polygon;
//import java.awt.Rectangle;
//import java.awt.geom.AffineTransform;
//import java.awt.geom.Line2D;
//import java.awt.geom.Point2D;
//import javafx.scene.shape.Line;
//import javafx.scene.transform.Rotate;

//<editor-fold defaultstate="collapsed" desc="Main">
public class Main implements Runnable{

    // https://netbeans.org/kb/73/java/editor-codereference_ru.html#display

    static boolean oj;

    @Override
    public void run(){
        try {
            Locale.setDefault(Locale.US);
        } catch (Exception e) {
        }
        oj = true;
        try {
            oj = System.getProperty("MYLOCAL") == null;
        } catch (Exception e) {
        }
//
        if (oj) {
            sc = new FastScanner(new InputStreamReader(System.in));
            out = new PrintWriter(new OutputStreamWriter(System.out));
        } else {
            try {
                sc = new FastScanner(new FileReader("input.txt"));
                out = new PrintWriter(new FileWriter("output.txt"));
            } catch (IOException e) {
                MLE();
            }
        }
        Solver s = new Solver();
        s.sc = sc;
        s.out = out;

        s.solve();
        if (!oj) {
            err.println("Time: " + (System.currentTimeMillis() - timeBegin) / 1e3);
            err.printf("Mem: %d\n", (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) >> 20);
        }
        out.flush();
    }

    private void show(int[] arr) {
        for (int v : arr) {
            err.print(" " + v);
        }
        err.println();
    }

    public static void exit() {
        err.println("Time: " + (System.currentTimeMillis() - timeBegin) / 1e3);
        err.printf("Mem: %d\n", (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) >> 20);
        out.flush();
        out.close();
        System.exit(0);
    }

    public static void MLE() {
        int[][] arr = new int[1024 * 1024][];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = new int[1024 * 1024];
        }
    }

    public static void main(String[] args) throws FileNotFoundException {
        //new Main().run();
        new Thread(null, new Main(), "myThread", 100 * 1024 * 1024).start();
    }

    static long timeBegin = System.currentTimeMillis();
    static FastScanner sc;
    static PrintWriter out;
    static PrintStream err = System.err;
}
    //</editor-fold>

//<editor-fold defaultstate="collapsed" desc="FastScanner">
class FastScanner {

    BufferedReader br;
    StringTokenizer st;

    FastScanner(InputStreamReader reader) {
        br = new BufferedReader(reader);
        st = new StringTokenizer("");
    }

    String next() {
        while (!st.hasMoreElements()) {
            try {
                st = new StringTokenizer(br.readLine());
            } catch (Exception ex) {
                return null;
            }
        }
        return st.nextToken();
    }

    int nextInt() {
        return Integer.parseInt(next());
    }

    long nextLong() {
        return Long.parseLong(next());
    }

    double nextDouble() {
        return Double.parseDouble(next());
    }

    String nextLine() {
        try {
            return br.readLine();
        } catch (IOException ex) {
            return null;
        }
    }
}
//</editor-fold>

class Solver {

    void aser(boolean OK) {
        if (!OK) {
            Main.MLE();
        }
    }

    FastScanner sc;
    PrintWriter out;
    static PrintStream err = System.err;

    long[] getAllDiv(long A){
        TreeSet<Long> arr = new TreeSet<>();
        for( long d = 1; d*d <= A; ++d ){
            if( A % d == 0 ) {
                arr.add(d);
                arr.add(A/d);
            }
        }
        int pos = 0;
        long[] a = new long[arr.size()];
        for (long x : arr) a[pos++] = x;
        return a;
    }

    long myPow(long p, int alfa){
        long ans = 1;
        for (int i = 0; i < alfa; i++) {
            ans *= p;
        }
        return ans;
    }

    void solve(){
        final long A = sc.nextLong();
        long[] divA = getAllDiv(A);
        TreeMap<Long,TreeSet<Integer>> P = new TreeMap<>();
        for (long div : divA) {
            --div;
            for (int alfa = 1; alfa <= 60; alfa++) {
                long p = (long)( pow( div, 1.0 / alfa ) + 0.5 );
                if( 2<=p && myPow(p,alfa)==div &&
                        valueOf(p).isProbablePrime(Integer.MAX_VALUE) ){
                    if( !P.containsKey(p) )
                        P.put(p, new TreeSet<>());
                    P.get(p).add(alfa);
                    break;
                }
            }
        }

        long[] dp0, dp;
        dp0 = new long[divA.length];
        dp0[0] = 1;
        for( long p : P.keySet() ){
            dp = dp0.clone();
            for( int alfa : P.get(p) ){
                long val = myPow(p, alfa) + 1;
                for( int ID = 0; ID < divA.length; ++ID){
                    long div = divA[ID];
                    if( 1e12 + 5 <= 1.0 * div * val ) break;
                    long toDiv = div * val;
                    int toID = binarySearch(divA, toDiv);
                    if( 0 <= toID ) dp[toID] += dp0[ID];
                }
            }
            //
            dp0 = dp;
        }
        out.println(dp0[divA.length - 1]);
    }

}


import java.util.*;
import java.io.*;
import java.lang.*;
import java.math.*;
public class A {
    public static void main(String[] args) throws Exception {
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        // Scanner scan = new Scanner(System.in);
        // PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
        long A = Long.parseLong(bf.readLine());
        Map<Long, HashSet<Integer>> m = new HashMap<Long, HashSet<Integer>>();
        Map<Long, Long> div = new HashMap<Long, Long>();
        ArrayList<Long> divisors = new ArrayList<Long>();
        long sqrt = (long)Math.sqrt(A);

        for(int i=1; i<sqrt; i++) {
            if(A % i == 0) {
                divisors.add(i+0L);
                if(1L*i*i != A) divisors.add(A/i);
            }
        }
        Collections.sort(divisors);

        hi: for(long i : divisors) {
            //System.out.println(i);
            boolean done = false;
            sqrt = (long)Math.sqrt(i-1);
            for(long j=2; j<=sqrt; j++) {
                if((i-1) % j == 0) {
                    long val = i-1;
                    double t = Math.log(val)/Math.log(j);
                    if(Math.abs(t - Math.round(t)) > 0.00001) continue hi;
                    int count = (int)Math.round(t);
                    HashSet<Integer> set = m.get(j);
                    if(set == null) {
                      set = new HashSet<Integer>();
                      m.put(j, set);
                    }
                    set.add(count);
                    div.put(i, j);
                    done = true;
                    break;
                }
            }
            if(!done && i != 1 && i != 2 ) {
                HashSet<Integer> set = m.get(i - 1);
                if(set == null) {
                   set = new HashSet<Integer>();
                   m.put(i - 1, set);
                }
                set.add(1);
                div.put(i, i-1);
            }
        }

       //
        ArrayList<Long> P = new ArrayList<Long>();
        for(long l : m.keySet()) P.add(l);
        Collections.sort(P);
        int[] dp = new int[divisors.size()];
        //System.out.println(P.size() + " " + divisors.size());
        Map<Long, Integer> divis = new HashMap<Long, Integer>();
        for(int i=0; i<divisors.size(); i++) divis.put(divisors.get(i), i);
        dp[0] = 1;
                long start = System.currentTimeMillis();
                long divv, pp, val;
                System.out.println(divisors.size());
                                System.out.println(P.size());
                                System.out.println(m.size());
        ArrayList<ArrayList<Long>> temp = new ArrayList<>();
        for(int i = 1; i <= P.size(); i++) {
          ArrayList<Long> list = new ArrayList<Long>();
          temp.add(list);
          pp = P.get(i - 1);
          for(int k : m.get(pp)) {
            val = (long)(Math.pow(pp, k) + 1);
            list.add(val);

          }
        }
        for(int i=1; i<=P.size(); ++i) {
            for(int j=divisors.size()-1; j>=0; --j) {
                divv = divisors.get(j);
                pp = P.get(i - 1);
                int iter = 0;
                ArrayList<Long> tempp = temp.get(i - 1);
                for(int k : m.get(pp)) {
                    val = tempp.get(iter++);
                    if(divv % val == 0)
                        dp[j] += dp[divis.get(divv/val)];
                }
            }
        }
                System.out.println(System.currentTimeMillis() - start);
        System.out.println(dp[divisors.size() - 1]);
       // System.out.println(P);
        // StringTokenizer st = new StringTokenizer(bf.readLine());
        // int[] a = new int[n]; for(int i=0; i<n; i++) a[i] = Long.parseInt(st.nextToken());
        // int n = Long.parseInt(st.nextToken());
        // int n = scan.nextInt();

        // out.close(); System.exit(0);
    }
}


import java.util.*;
import java.io.*;
public class EdE {

	public static void main(String[] args) throws Exception{
		int num = 998244353;

		// TODO Auto-generated method stub
 		BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
 		PrintWriter out = new PrintWriter(System.out);
 		StringTokenizer st = new StringTokenizer(bf.readLine());
 		int n = Integer.parseInt(st.nextToken());
 		int k = Integer.parseInt(st.nextToken());
 		long ans = 0;
 		for (int i = 0;i<n-k;i++){
 			//ans+= (-1)^i*(n-k choose i)* (n-k-i)^n
 			long ks = 1;
			for(int j = 0;j<i;j++){
				ks = ks*(n-k-j)%num;
			}
			for(int j = 1;j<=i;j++){
				ks = ks*power(j, num-2, num)%num;
			}
 			if (i%2 == 0){

 				ans+= ks * power(n-k-i, n, num)%num;
 			}
 			else{
 				ans-= ks* power(n-k-i, n, num)%num;
 			}
 			ans = ans%num;
 		}
 		if (k != 0)
 			ans= ans*2%num;

 		for(int j = n;j>n-k;j--){
 			ans = ans*j%num;
 		}
 		for(int j = 1;j<=k;j++){
 			ans = ans*power(j, num-2, num)%num;
 		}

 		while (ans < 0){
 			ans = ans+num;
 		}

 		out.println(ans);
 		out.close();

 	}

	public static int power(long x, long y, long mod){
		long ans = 1;
		while(y>0){
			if (y%2==1)
				ans = (ans*x)%mod;
			x = (x*x)%mod;
			y/=2;
		}
		return (int)(ans);
	}
 }

//StringJoiner sj = new StringJoiner(" ");
//sj.add(strings)
//sj.toString() gives string of those stuff w spaces or whatever that sequence is


import java.io.*;
import java.util.*;

import static java.lang.Math.*;
import static java.util.Arrays.*;

public class cf1342e {

    public static void main(String[] args) throws IOException {
        int n = rni(), k, fact[] = new int[n + 1], ifact[] = new int[n + 2], ans = 0;
        long kl = nl();
        if(kl >= n) {
            prln(0);
            close();
            return;
        }
        k = (int)kl;
        fact[0] = fact[1] = ifact[0] = ifact[1] = 1;
        for(int i = 2; i <= n; ++i) {
            fact[i] = fmul(fact[i - 1], i);
            ifact[i] = fpow(fact[i], fmod - 2);
        }
        for(int i = 0; i <= n - k; ++i) {
            ans = (ans + ((i % 2 == 0 ? 1 : -1) * fmul(fpow(n - k - i, n), fmul(fact[n - k], fmul(ifact[i], ifact[n - k - i]))) + fmod) % fmod) % fmod;
        }
        ans = fmul(fmul(ans, fact[n]), fmul(ifact[k], ifact[n - k]));
        prln(k == 0 ? ans : fmul(ans, 2));
        close();
    }

    static int fmod = 998244353;

    static int fpow(int a, int b) {
        if(a == 0) {
            return 0;
        }
        int ans = 1;
        while(b > 0) {
            if((b & 1) > 0) {
                ans = fmul(ans, a);
            }
            a = fmul(a, a);
            b >>= 1;
        }
        return ans;
    }

    static int fmul(int a, int b) {
        int ans = 0;
        while(b > 0) {
            if((b & 1) > 0) {
                ans = (ans + a) % fmod;
            }
            a = (a << 1) % fmod;
            b >>= 1;
        }
        return ans;
    }

    static BufferedReader __in = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter __out = new PrintWriter(new OutputStreamWriter(System.out));
    static StringTokenizer input;
    static Random rand = new Random();

    // references
    // IBIG = 1e9 + 7
    // IMAX ~= 2e10
    // LMAX ~= 9e18

    // constants
    static final int IBIG = 1000000007;
    static final int IMAX = 2147483647;
    static final int IMIN = -2147483648;
    static final long LMAX = 9223372036854775807L;
    static final long LMIN = -9223372036854775808L;
    // math util
    static int minof(int a, int b, int c) {return min(a, min(b, c));}
    static int minof(int... x) {if(x.length == 1) return x[0]; if(x.length == 2) return min(x[0], x[1]); if(x.length == 3) return min(x[0], min(x[1], x[2])); int min = x[0]; for(int i = 1; i < x.length; ++i) if(x[i] < min) min = x[i]; return min;}
    static long minof(long a, long b, long c) {return min(a, min(b, c));}
    static long minof(long... x) {if(x.length == 1) return x[0]; if(x.length == 2) return min(x[0], x[1]); if(x.length == 3) return min(x[0], min(x[1], x[2])); long min = x[0]; for(int i = 1; i < x.length; ++i) if(x[i] < min) min = x[i]; return min;}
    static int maxof(int a, int b, int c) {return max(a, max(b, c));}
    static int maxof(int... x) {if(x.length == 1) return x[0]; if(x.length == 2) return max(x[0], x[1]); if(x.length == 3) return max(x[0], max(x[1], x[2])); int max = x[0]; for(int i = 1; i < x.length; ++i) if(x[i] > max) max = x[i]; return max;}
    static long maxof(long a, long b, long c) {return max(a, max(b, c));}
    static long maxof(long... x) {if(x.length == 1) return x[0]; if(x.length == 2) return max(x[0], x[1]); if(x.length == 3) return max(x[0], max(x[1], x[2])); long max = x[0]; for(int i = 1; i < x.length; ++i) if(x[i] > max) max = x[i]; return max;}
    static int powi(int a, int b) {if(a == 0) return 0; int ans = 1; while(b > 0) {if((b & 1) > 0) ans *= a; a *= a; b >>= 1;} return ans;}
    static long powl(long a, int b) {if(a == 0) return 0; long ans = 1; while(b > 0) {if((b & 1) > 0) ans *= a; a *= a; b >>= 1;} return ans;}
    static int fli(double d) {return (int)d;}
    static int cei(double d) {return (int)ceil(d);}
    static long fll(double d) {return (long)d;}
    static long cel(double d) {return (long)ceil(d);}
    static int randInt(int min, int max) {return rand.nextInt(max - min + 1) + min;}
    // array util
    static void reverse(int[] a) {for(int i = 0, n = a.length, half = n / 2; i < half; ++i) {int swap = a[i]; a[i] = a[n - i - 1]; a[n - i - 1] = swap;}}
    static void reverse(long[] a) {for(int i = 0, n = a.length, half = n / 2; i < half; ++i) {long swap = a[i]; a[i] = a[n - i - 1]; a[n - i - 1] = swap;}}
    static void reverse(char[] a) {for(int i = 0, n = a.length, half = n / 2; i < half; ++i) {char swap = a[i]; a[i] = a[n - i - 1]; a[n - i - 1] = swap;}}
    static void shuffle(int[] a) {int n = a.length - 1; for(int i = 0; i < n; ++i) {int ind = randInt(i, n); int swap = a[i]; a[i] = a[ind]; a[ind] = swap;}}
    static void shuffle(long[] a) {int n = a.length - 1; for(int i = 0; i < n; ++i) {int ind = randInt(i, n); long swap = a[i]; a[i] = a[ind]; a[ind] = swap;}}
    static void rsort(int[] a) {shuffle(a); sort(a);}
    static void rsort(long[] a) {shuffle(a); sort(a);}
    static int[] copy(int[] a) {int[] ans = new int[a.length]; for(int i = 0; i < a.length; ++i) ans[i] = a[i]; return ans;}
    static long[] copy(long[] a) {long[] ans = new long[a.length]; for(int i = 0; i < a.length; ++i) ans[i] = a[i]; return ans;}
    static char[] copy(char[] a) {char[] ans = new char[a.length]; for(int i = 0; i < a.length; ++i) ans[i] = a[i]; return ans;}
    static int[] sorted(int[] a) {int[] ans = copy(a); sort(ans); return ans;}
    static long[] sorted(long[] a) {long[] ans = copy(a); sort(ans); return ans;}
    static int[] rsorted(int[] a) {int[] ans = copy(a); rsort(ans); return ans;}
    static long[] rsorted(long[] a) {long[] ans = copy(a); rsort(ans); return ans;}
    // graph util
    static List<List<Integer>> graph(int n) {List<List<Integer>> g = new ArrayList<>(); for(int i = 0; i < n; ++i) g.add(new ArrayList<>()); return g;}
    static List<List<Integer>> graph(List<List<Integer>> g, int m) throws IOException {for(int i = 0; i < m; ++i) connect(g, rni() - 1, ni() - 1); return g;}
    static List<List<Integer>> graph(int n, int m) throws IOException {return graph(graph(n), m);}
    static List<List<Integer>> dgraph(List<List<Integer>> g, int m) throws IOException {for(int i = 0; i < m; ++i) connecto(g, rni() - 1, ni() - 1); return g;}
    static List<List<Integer>> dgraph(List<List<Integer>> g, int n, int m) throws IOException {return dgraph(graph(n), m);}
    static List<Set<Integer>> sgraph(int n) {List<Set<Integer>> g = new ArrayList<>(); for(int i = 0; i < n; ++i) g.add(new HashSet<>()); return g;}
    static List<Set<Integer>> sgraph(List<Set<Integer>> g, int m) throws IOException {for(int i = 0; i < m; ++i) connect(g, rni() - 1, ni() - 1); return g;}
    static List<Set<Integer>> sgraph(int n, int m) throws IOException {return sgraph(sgraph(n), m);}
    static List<Set<Integer>> dsgraph(List<Set<Integer>> g, int m) throws IOException {for(int i = 0; i < m; ++i) connecto(g, rni() - 1, ni() - 1); return g;}
    static List<Set<Integer>> dsgraph(List<Set<Integer>> g, int n, int m) throws IOException {return dsgraph(sgraph(n), m);}
    static void connect(List<? extends Collection<Integer>> g, int u, int v) {g.get(u).add(v); g.get(v).add(u);}
    static void connecto(List<? extends Collection<Integer>> g, int u, int v) {g.get(u).add(v);}
    static void dconnect(List<? extends Collection<Integer>> g, int u, int v) {g.get(u).remove(v); g.get(v).remove(u);}
    static void dconnecto(List<? extends Collection<Integer>> g, int u, int v) {g.get(u).remove(v);}
    // input
    static void r() throws IOException {input = new StringTokenizer(__in.readLine());}
    static int ri() throws IOException {return Integer.parseInt(__in.readLine());}
    static long rl() throws IOException {return Long.parseLong(__in.readLine());}
    static int[] ria(int n) throws IOException {int[] a = new int[n]; input = new StringTokenizer(__in.readLine()); for(int i = 0; i < n; ++i) a[i] = Integer.parseInt(input.nextToken()); return a;}
    static int[] riam1(int n) throws IOException {int[] a = new int[n]; input = new StringTokenizer(__in.readLine()); for(int i = 0; i < n; ++i) a[i] = Integer.parseInt(input.nextToken()) - 1; return a;}
    static long[] rla(int n) throws IOException {long[] a = new long[n]; input = new StringTokenizer(__in.readLine()); for(int i = 0; i < n; ++i) a[i] = Long.parseLong(input.nextToken()); return a;}
    static char[] rcha() throws IOException {return __in.readLine().toCharArray();}
    static String rline() throws IOException {return __in.readLine();}
    static int rni() throws IOException {input = new StringTokenizer(__in.readLine()); return Integer.parseInt(input.nextToken());}
    static int ni() {return Integer.parseInt(input.nextToken());}
    static long rnl() throws IOException {input = new StringTokenizer(__in.readLine()); return Long.parseLong(input.nextToken());}
    static long nl() {return Long.parseLong(input.nextToken());}
    // output
    static void pr(int i) {__out.print(i);}
    static void prln(int i) {__out.println(i);}
    static void pr(long l) {__out.print(l);}
    static void prln(long l) {__out.println(l);}
    static void pr(double d) {__out.print(d);}
    static void prln(double d) {__out.println(d);}
    static void pr(char c) {__out.print(c);}
    static void prln(char c) {__out.println(c);}
    static void pr(char[] s) {__out.print(new String(s));}
    static void prln(char[] s) {__out.println(new String(s));}
    static void pr(String s) {__out.print(s);}
    static void prln(String s) {__out.println(s);}
    static void pr(Object o) {__out.print(o);}
    static void prln(Object o) {__out.println(o);}
    static void prln() {__out.println();}
    static void pryes() {__out.println("yes");}
    static void pry() {__out.println("Yes");}
    static void prY() {__out.println("YES");}
    static void prno() {__out.println("no");}
    static void prn() {__out.println("No");}
    static void prN() {__out.println("NO");}
    static void pryesno(boolean b) {__out.println(b ? "yes" : "no");};
    static void pryn(boolean b) {__out.println(b ? "Yes" : "No");}
    static void prYN(boolean b) {__out.println(b ? "YES" : "NO");}
    static void prln(int... a) {for(int i = 0, len = a.length - 1; i < len; __out.print(a[i]), __out.print(' '), ++i); __out.println(a[a.length - 1]);}
    static void prln(long... a) {for(int i = 0, len = a.length - 1; i < len; __out.print(a[i]), __out.print(' '), ++i); __out.println(a[a.length - 1]);}
    static <T> void prln(Collection<T> c) {int n = c.size() - 1; Iterator<T> iter = c.iterator(); for(int i = 0; i < n; __out.print(iter.next()), __out.print(' '), ++i); if(n >= 0) __out.println(iter.next()); else __out.println();}
    static void h() {__out.println("hlfd");}
    static void flush() {__out.flush();}
    static void close() {__out.close();}
}