您的位置:首页 > 其它

牛客练习赛13 --d(逆康拓展开)

2018-03-18 00:02 323 查看
题目链接: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
){
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: