//带分数的优化
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 20;
int ans;
int n;
bool st[N],backup[N];
bool check(int a,int c)
{
long long b = (long long)n*c-(long long)a*c;//写出b的表达式
if(!a||!b||!c)return false;//判断a,b,c中是否有0,有则直接返回
//此时之所以需要备份st数组,是因为如果改变st数组,会影响到正在进行枚举的a,c,所以直接备份一个数组,在其基础上进行判断和改变不会影响到a,c的枚举,并且若此次方案不满足,当下一次循环到该位置的时候就会重新备份一个数组,这样对程序不会造成什么影响
memcpy(backup,st,sizeof st);//复制数组,memcpy(复制到的数组(结果),被复制的数组的开始地方,需要复制的长度)
while(b)//循环,只要b不为0
{//之所以复制一下
int x = b%10;//获取b的个位
b /=10;//整除
if(!x||backup[x])return false;//如果b中有0,或者b中的数字已经被使用,就返回false
backup[x]=true;//如果该数字在a,c中一次都未使用,则置为true
}
//判断一下1~9中的数字是不是都已经出现且只出现一次
for(int i=1;i<=9;i++)
{
if(!backup[i])return false;
}
return true;
}
void dfs_c(int u,int a,int c)
{
if(u>9)return;//判断此时是否已经枚举结束,如果大于9,说明已经选出了9个数字,自然不需要继续枚举
if(check(a,c))ans++;//判断此时的a,c是否满足条件,满足则加1
for(int i=1;i<=9;i++)
{
if(!st[i])//判断这个数字是否被用过
{
st[i]=true;
dfs_c(u+1,a,c*10+i);//枚举c的值,并传递c改变之后的值
st[i]=false;//恢复现场
}
}
}
void dfs_a(int u,int a){//u就是表示此时已经有几个确定的值
if(a>=n)return;//此时如果a本身就比n大,就没有枚举的必要,直接不满足
if(a)dfs_c(u,a,0);//此时是u而不是u+1,是因为此时的u是对c而言,c并没有一个确定的值,所以需要从0开始,而不是u+1,那样c一开始就会有一个确定的值,就是错误的
for(int i=1;i<=9;i++)
{
if(!st[i])//判断这个数字是否被用过
{
st[i]=true;
dfs_a(u+1,a*10+i);//枚举a的值,并传递a改变之后的值
st[i]=false;//恢复现场
}
}
}
int main()
{
scanf("%d ",&n);
dfs_a(0,0);//这个u是对a而言,a还没有一个确定的值
cout<<ans<<endl;
return 0;
}