[入门组模拟赛]幸运数与排列

题目描述

一个数是幸运数当且仅当这个数仅由4和7构成,比如47,744,4747。

    在1到n的全排列中字典序第k小的排列中,有多少个幸运数在排列中的位置编号也是幸运数。

输入

一行两个整数n,k。

输出

一个整数表示答案。如果不存在第k小的排列,则输出-1。

样例输入

7 4

样例输出

1

提示

对于30%的数据,n<=8

对于60%的数据,n<=100

对于100%的数据,n,k<=10^9

#include<bits/stdc++.h>
using namespace std;
int n,k,t;
long long p[21],opt[21],q1,ans;
bool used[21];
void gen(long long x)
{
    if(x>q1) return ;
    ans++;
    gen(x*10+4);
    gen(x*10+7);
}
bool chk(int x)
{
    while(x>0)
    {
        if(x%10!=4&&x%10!=7) return 0;
        x/=10;
    }
    return 1;
}
int main()
{
    scanf("%d%d",&n,&k);
    p[0]=1;
    for(int i=1;i<=19;i++)
        p[i]=p[i-1]*i;
    if(n<=14&&p[n]<k)
        return !printf("-1");
    for(int i=1;i<=19;i++)
        if(p[i]>=k)
        {
            t=i;
            break;
        }
    q1=n-t;
    gen(4);
    gen(7);
    k--;
    for(int i=1;i<=t;i++)
    {
        int tmp=k/p[t-i],num=0;
        for(int j=1;j<=t;j++)
            if(used[j]==0)
            {
                num++;
                if(num==tmp+1)
                {
                    opt[i]=j;
                    used[j]=1;
                }
            }
        k=k%p[t-i];
    }
    for(int i=1;i<=t;i++)
        if(chk(q1+opt[i])&&chk(q1+i))
            ans++;
    printf("%lld",ans);
    return 0;
}
posted @ 2020-07-05 20:34  牛大了的牛大  阅读(255)  评论(0编辑  收藏  举报