题目链接:
https://www.nowcoder.com/acm/contest/70/D
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define ll long long
const int mx = 55;
//const int mod = 1e9 + 7;
using namespace std;
ll num[2049],ans;
int add;
static const int FAC[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880,3628800,39916800,479001600};
void da(ll x){
ll a = 1LL * 10 * x + 4, b = 1LL * 10 * x + 7;
if(a > 1e10) return;
da(a);
num[add++] = a;
// cout<<a<<endl;
if(b > 1e10) return;
da(b);
num[add++] = b;
// cout<<b<<endl;
}
ll cmp(int l, int r){
ll sum = 0;
int le =lower_bound(num, num+add, l) - num;
int ri =lower_bound(num, num+add, r) - num;
if(num[ri] >r) ri--;
//if()
//cout<<le<<endl;
sum = (ri - le + 1);
// cout<<sum<<endl;
return sum;
}
bool check(int x){
int a;
while(x){
a = x %10;
if(a == 4 || a ==7){
x /= 10;
}
else break;
}
if(x)
return false;
else
return true;
}
void decantor(int x, int n, int qi)
{
x -=1; //最小从一开始
vector<int> v; // 存放当前可选数
// vector<int> a; // 所求排列组合
for(int i= 0;i<=n;i++)
v.push_back(qi + i);
for(int i=n;i>=1;i--)
{
int r = x % FAC[i-1];
int t = x / FAC[i-1];
x = r;
sort(v.begin(),v.end());// 从小到大排序
// a.push_back(v[t]); // 剩余数里第t+1个数为当前位
if(check(v[t]) && check (qi + n - i))
ans++;
v.erase(v.begin()+t); // 移除选做当前位的数
}
}
int main(){
ll n, k;
add = 0;
da(0); //add = 1022;
sort(num, num + add);
while(~scanf("%d%d",&n,&k)){
if(n < 13 &&k > FAC[n]){
puts("-1");
continue;
}
int cnt = lower_bound(FAC,FAC+13,k) - FAC;
if(FAC[cnt] != k) cnt--;
ans = 0;
ans += cmp(1,n-cnt-1);
decantor(k, cnt+1, n - cnt);
cout<<ans<<endl;
}
return 0;
}