把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

【找规律】六边形 纪中集训



这题一眼看穿其找规律本质
然而如何找规律,这是一个问题
此生最恨结论题(找规律算其中一种吧)、构造题

不得不说此题是打表好题,找不到规律果断skip之后回来还是找不到规律,然后为了30%的部分分卑微地画了100个正六边形


考场上的思路:
首先,它每一圈的个数是有规律的:1、6、12、18······
然后,显然同一圈的 i-1 i i+1是相邻的
那么不同圈上的相邻的怎么算呢?
嗯,这是个问题。
大概画了几圈之后发现这个规律非常的隐晦 (其实我根本就没有找到)
这些正六边形有的对着两个,有的对着一个,完全不知道怎么搞


然而OI的有趣之处就在于此(怎么就开始哲学了)

所谓正难则反,既然找每一个六边形的相邻的已生成的六边形有哪些找不到,我们就想想如何通过已有的推哪些六边形是跟现在的相邻的。
我们就把视线转移到了一个个周围一圈6个的这样的图形:

由于我们的思路已经转移到了“我为人人”的境界,所以i-1以内的数我们就不用管了,因为他们自己会推过来

i+1由i拓展得到的 所以一定与i相邻
然后最难搞的就是其它的数

首先,通过观察,可以知道他们一定都是连续的(逆时针绕圈圈)

其次,i=1的情况明显可以打表,当1移动到2的时候,我们会发现,外面那一圈最大的7,在2的那个圈圈里面变成了最小的。
以此类推后面的圈圈,这是第二个重要的结论。
然后就是这些连续的数的个数,显然就是6(一圈的个数)-i-1以内与它相邻的个数-1(第i+1个)

然后就是代码的细节实现问题了:

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define MAXN 10005
#define INF 0x3f3f3f3f
#define LL long long
int cnt[MAXN],mx[MAXN],id[MAXN],tot[6];
bool vis[MAXN][5];
//cnt[i]:i与多少个i-1以内的数相邻 当前点的决策只与他们有关(虽然这个数组只用于统计个数) 
//mx[i]:i的那一圈里面最大的数 =mx[i-1]+6/*一圈6个*/-cnt[i]-1
//当前状态要去更新mx[i-1]到mx[i]的vis和cnt 
//i+1是由i拓展得到的 所以一定与i相邻
//vis[i][j]表示第i号的颜色j还能不能用 1表示相邻的已用过,不能用
//tot[i]表示i号颜色的种数 
void Init()
{
	cnt[1]=0,mx[1]=7,id[1]=1,tot[1]=1;
	vis[2][1]=vis[3][1]=vis[4][1]=vis[5][1]=vis[6][1]=vis[7][1]=1;
	cnt[2]++;cnt[3]++;cnt[4]++;cnt[5]++;cnt[6]++;cnt[7]++;
	for(int i=2;i<=10000;i++)
	{
		mx[i]=min(mx[i-1]+6-cnt[i]-1/*减去第i+1个数*/-1/*从0开始计数*/,10001/*这里要稍微改大一点 刚好是10000在n=10000时就不能过*/);
		//有可能本来mx[]是一个很大的数(不妨设为inf) 也就是说,是一个完全达不到的状态 对结果没有任何影响 
		//但如果取了10000 循环到mx[i-1]-mx[i]且他们都等于10000时,就错误地把10000更新了 
		//所以这里也应该设置一个达不到的状态 乱更新也没有什么关系 只要保证在10004以内不会RE就可以了 
		int lt/*least*/=INF;int lid;
		for(int j=1;j<=5;j++)
			if(!vis[i][j]&&lt>tot[j])
				lt=tot[j],lid=j;
		id[i]=lid,tot[lid]++;
		for(int j=mx[i-1];j<=mx[i];j++)
			vis[j][lid]=1,cnt[j]++;
		vis[i+1][lid]=1,cnt[i+1]++;//cnt表示它自己被别人算的 前面的减去第i+1个数是减去它的第i+1个数 
	}
}
int main()
{
	Init();
	int T;
	scanf("%d",&T);
	while(T--)
	{
		int n;
		scanf("%d",&n);
		printf("%d\n",id[n]);
	}
	return 0;
}
posted @ 2020-10-03 18:11  Starlight_Glimmer  阅读(33)  评论(0编辑  收藏  举报  来源
浏览器标题切换
浏览器标题切换end