传说中的代码两分钟推理一小时?
听说有许多大神秒出结论我真的是太菜了。。
先分析题目,大概就是有n条直线,不能有三条直线交于一点,引入了“层”的概念,问第k层最少有多少个。
那我们先分析一下题目里面就有的n=3的情况,题目中的那个图里面
第一层:3段
第二层:4段
第三层:2段
那么如果我们把图倒过来呢?
很明显,如果我们把那个图倒过来的话,倒过来的图仍然满足性质,同时我们可以得到
第一层:2段
第二层:4段
第三层:3段
我们发现倒过来的话,层数所对应的段数也倒了过来,那么同时第一层的答案更优
所以正的第三层和倒着的第一层是等效的
那么我们就得到了一个性质:对称性
然后我们再画一下n=4的
第一层:2段
第二层:4段
第三层:6段
第四层:4段
我们可以从中发现,新加一条直线是对一部分函数没有影响的,同时我们发现加了一条线,之前的1+2=3个交点就变成了1+2+3=6个交点
那么我们从段数的定义出发,段数来源与交点,那么我们给交点编个号
如果我们从上往下算层数(因为对称嘛,所以从上往下和从下往上是等效的)
以点A举例,我们可以发现,一个交点可以延伸出两段
那么两个交点是否延伸出四段呢?
并不是!
两个交点确实延伸出四段,但是这四段中的其中两段一定相交,又形成了一个交点,那么也就是3个交点延伸出4段。
所以x个交点,可以生成x+1段
第一层过点A->2段
第二层过点BAC->4段
第三层过点DBECF->6段
第四层过点DEF->4段
我们发现点数都是:
1,3,5…..
那么综合上面的推理和观察(乱猜)法段数就是
2,4,6…..
注意n=1是特殊的,此时Ans=1
因为k和n-k+1等效,所以在k和n-k+1中选比较小的那个
那么答案就是
Ans = (n==1)?1:(min(k,n-k+1)*2)
code:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
int n,k;
scanf("%d%d",&n,&k);
if(n==1) printf("1\n");
else printf("%d\n",min(k,n-k+1)*2);
return 0;
}