记录第一次补困难题,竟然思路会一点,虽然我不会代码写出来
整体思路:首先,如果按字典排序的个数<m,就输出-1;然后dfs排列1-n中只含4和7的数字,1<=n<=1e9,n最多为九位数,
一位数 2的1次方 两位数
2的2次方 三位数 2的3次方 ..... ..... 九位数 2的九次方 总共 2的10次方-2 然后算出来按字典排序的第k个序列,当g<=n-k时,前g个数字不变换,仍为本身,只需算后n-k+1-n的数字即可,然后看只含4和7的位置的数字也只能含有4和7,符合题意ans++,最后输出ans即可。
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,ans;
bool st[20];
int f(int x)
{
int s=1;
for(int i=1;i<=x;i++)
{
s*=i;
if(s>m)
return m+1;
}
return s;
}
int getax(int g)
{
int k=1;
while(f(k)<m)
k++;
if(g<=n-k)
return g;
memset(st,0,sizeof (st));
int rank=m;
for(int i=n-k+1;i<=n;i++)
{
for(int j=1;j<=k;j++)
{
if(!st[j])
{
int t=f(n-i);
if(t<rank)
rank-=t;
else
{
if(g==i)
return j+n-k;
st[j]=true;
break;
}
}
}
}
return -1;
}
//bool only47(int a1)
//{
// string str=to_string(a1);
// for(auto c:str)
// {
// if(c!='4'&&c!='7')
// return false;
// }
// return true;
//}
bool only47(int a1)
{
string s=to_string(a1);
for(int i=0;i<s.size();i++)//字符串下标从0开始
{
if(s[i]!='4'&&s[i]!='7')
return false;
}
return true;
}
void dfs(int d)
{
if(d>n)
return ;
if(d&&only47(getax(d)))
ans++;
dfs(d*10+4);
dfs(d*10+7);
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
if(f(n)<m)
{
cout<<"-1";
}
else
{
dfs(0);
cout<<ans;
}
return 0;
}