P1384 幸运数与排列(dfs&NCantor)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1384 幸运数与排列(dfs&NCantor)相关的知识,希望对你有一定的参考价值。

P1384 幸运数与排列

幸运数爆搜即可。

排列当 k k k很大时,因为 13 ≈ 6.2 × 1 0 9 13\\approx 6.2\\times 10^9 136.2×109

所以只会改变后面的几位。

前面是不变的。

找到分界点,分界点前面的数和编号是相同的,答案就是其个数,后面就逆康托展开一下,然后特判即可。

// Problem: P1384 幸运数与排列
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1384
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// Date: 2021-07-23 12:50:16
// --------by Herio--------

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull; 
const int N=1e3+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define ios ios::sync_with_stdio(false),cin.tie(0) 
void Print(int *a,int n){
	for(int i=1;i<n;i++)
		printf("%d ",a[i]);
	printf("%d\\n",a[n]); 
}
int n,k;
int num[N],c1,c2,a[N];
ll ans;
ll fac[20];
void dfs(ll x,ll y){
	y+=4*x;
	if(y>n) return;
	num[++c1]=y;
	dfs(x*10,y);
	y+=3*x;
	if(y>n) return;
	num[++c1]=y;
	dfs(x*10,y);
}
bool ck(int x){
	for(int i=c1;i;i--){
		if(num[i]==x) return true;
		else if(num[i]<x) return false;
	}
	return false;
}
int vis[22],b[22],c3,c[22],p;
void solve(int cc){
	mst(vis,0);
	for(int i=1;i<=cc;i++){
		int y=k/fac[cc-i];
		for(int j=1;j<=cc;j++){
			if(!vis[j]){
				if(!y){
					 b[++c3]=c[j];vis[j]=1;
					 break;
				}
				y--;
			}
		}
		k%=fac[cc-i];
	}
	for(int i=1;i<=c2;i++){
		if(ck(b[a[i]-p+1])) ans++;
	}
}
int main(){
	scanf("%d%d",&n,&k);fac[0]=1;
	for(int i=1;i<=20;i++) fac[i]=fac[i-1]*i;
	if(n<12&&fac[n]<k) return puts("-1"),0;
	dfs(1,0);
	if(!c1) return puts("-1"),0;
	sort(num+1,num+c1+1);
	int cnt=15;
	while(cnt){
		if(fac[cnt]<k) break;
		cnt--;
	}
	k--;
	p=n-cnt;
	//Print(num,c1);
	for(int i=c1;num[i]>=p;i--)
		a[++c2]=num[i];
	if(!c2||!cnt) return printf("%d\\n",c1),0;
	ans=c1-c2;
	for(int i=p;i<=n;i++) c[i-p+1]=i;
	//printf("ans=%lld\\n",ans);
	solve(cnt+1);
	//printf("------\\n");
	if(!ans) return puts("-1"),0;
	printf("%lld\\n",ans);
	return 0;
}

以上是关于P1384 幸运数与排列(dfs&NCantor)的主要内容,如果未能解决你的问题,请参考以下文章

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

DFS+剪枝Aw842.排列数 & Aw843.N-皇后问题

for循环枚举法,全排列+dfs,补充浮点数注意事项

P2567 [SCOI2010]幸运数字 DFS+容斥定理

幸运数(DFS做法)

排列序号