CF285D (打表+搜索)

Posted huayucaiji 的博客小屋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF285D (打表+搜索)相关的知识,希望对你有一定的参考价值。

CF285D

解题思路

这个题,我一看,哦,\\(n\\leq 16\\),而且又是输入只有 \\(n\\)。果断打表啊!

关键在于如何快速打表。

我们可以先找出 \\(C=(1,2,\\cdots,n)\\) 的方案数,然后再乘以 \\(n!\\) 就是总方案数了。我们如果爆搜的话就是 \\(O(n*n!)\\)。看起来好像跑的很慢 ,其实加上合理剪枝跑的速度还可以接受。

我们如果手玩一下 \\(n\\leq 5\\) 的结果,或者让程序跑 \\(n\\leq 12\\) 的答案(这部分跑的飞快),你就会发现 \\(n\\) 为偶数的时候,答案是 \\(0\\)。这样我们对于 \\(n\\) 为偶数的情况又可以不算了。

如果你像追求更高的效率,可以使用 Meet-in-the-middle。当然,不加这个优化也可以在 \\(6\\ min\\) 内跑完,最后打表即可。

代码

//Don\'t act like a loser.
//This code is written by huayucaiji
//You can only use the code for studying or finding mistakes
//Or,you\'ll be punished by Sakyamuni!!!
#include<bits/stdc++.h>
using namespace std;

int read() {
	char ch=getchar();
	int f=1,x=0;
	while(ch<\'0\'||ch>\'9\') {
		if(ch==\'-\')
			f=-1;
		ch=getchar();
	}
	while(ch>=\'0\'&&ch<=\'9\') {
		x=x*10+ch-\'0\';
		ch=getchar();
	}
	return f*x;
}

const int MAXN=16,MOD=1e9+7; 

int n;
int ans[MAXN],jc[MAXN];
bool vis[MAXN][2];

void dfs(int n,int x) {
	if(x==n+1) {
		ans[n]++;
		return ;
	}
	for(int i=1;i<=n;i++) {
		if(!vis[i][0]) {
			int j=(x-1-i+2+n)%n;
			if(!j) {
				j=n;
			}
			if(!vis[j][1]) {
				vis[i][0]=1;
				vis[j][1]=1;
				dfs(n,x+1);
				vis[i][0]=0;
				vis[j][1]=0;
			}
		}
	}
}

int main() {
	//freopen(".in","r",stdin);
	//freopen(".out","w",stdout);

	int t=16;
	jc[0]=1;
	for(int i=1;i<=t;i++) {
		jc[i]=1ll*jc[i-1]*i%MOD;
		if(i&1) {
			dfs(i,1);
			ans[i]=1ll*ans[i]*jc[i]%MOD;
		}
		else {
			ans[i]=0;
		}
		printf("ans[%d]=%d;\\n",i,ans[i]);
	}

	//fclose(stdin);
	//fclose(stdout);
	return 0;
}

不会有人直接交这个程序吧。。。。

这个是打表用的(坑一下直接抄题解的人)

以上是关于CF285D (打表+搜索)的主要内容,如果未能解决你的问题,请参考以下文章

codeforces Goodbye2018 C. New Year and the Permutation Concatenation 傻瓜解法找规律+打表

数位DPCF55D Beautiful numbers

zoj 2723 Semi-Prime(素筛打表+搜索优化)

CF-1362C. Johnny and Another Rating Drop

CF-1362C. Johnny and Another Rating Drop

如何从后台弹出片段