题解:
首先显而易见的:填棋子的过程就是划分区间的过程,那么为了框出边界,我们需要在1,n上填好
然后就在考场上傻傻的讨论区间的奇偶性,过了样例就跪了大数据,果然不证明的结论都是胡扯。
实际上这道题目有一个结论
f[x]=__builtin_popcount(x)-1
__builtin_popcount(x):x的二进制中有多少个一
怎么跟二进制扯上关系的?
我们可以发现:如果一开始0号位有棋子,为了让1号位的棋子免费,我们需要填上2号位的格子
为了让2号位的棋子免费,我们需要填上4号位的棋子…….
2的幂啊,我们发现这样填的话首先填16的话这一堆都不用管了
因此,我们在相邻的两个棋子之间,只有把棋子放在2的整数幂的位置才能保证答案最小
我们利用倍增的思想,贪心的往空隙中放置相聚尽量远且位置是2的整数幂的棋子(因为这样中间的都不用管了)
代码:
#include <cstdio>
#include <algorithm>
#define LL long long
using namespace std;
int m;LL a[10],n;
int work(LL x)
{
int ans=0;
while (x) ans+=(x&1),x>>=1;
return ans;
}
int main()
{
freopen("chess.in","r",stdin);
freopen("chess.out","w",stdout);
scanf("%lld%d",&n,&m);
if(m==0)
{
printf("%d",work(n-1)+1);
return 0;
}
bool h1=0,hn=0;
for(int i=1;i<=m;i++)
{
scanf("%lld",&a[i]);
if (a[i]==1) h1=1;
if (a[i]==n) hn=1;
}
int ans=0;
if (!h1) a[++m]=1,ans++;
if (!hn) a[++m]=n,ans++;
sort(a+1,a+m+1);
for(int i=2;i<=m;i++) ans+=work(a[i]-a[i-1])-1;
printf("%d",ans);
}