[入门组模拟赛]幸运数与排列
题目描述
一个数是幸运数当且仅当这个数仅由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; }