T1 A
题意
给出一些棋子的位置,对于每一个棋子,可以左移一格或两格,前提是目标位置上无棋子
移出棋盘(即坐标
≤
0
\le 0
≤0)则记为挂掉,问挂掉的顺序有多少种
正解
观察发现有如下的情况,棋子挂掉的顺序是任意的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2m2WJ5X3-1603874684272)(C:\Users\am\AppData\Roaming\Typora\typora-user-images\image-20201028162744488.png)]
考虑目前棋子坐标
1
,
3
,
5
,
⋯
,
(
2
i
−
1
)
1,3,5,\cdots,(2i-1)
1,3,5,⋯,(2i−1),共
i
i
i个,加入棋子
如果加入到
2
i
2i
2i,必须挂掉一个才能维护上述形态,
a
n
s
×
(
i
+
1
)
ans\times (i+1)
ans×(i+1)
如果加入到
≥
2
i
+
1
\ge 2i+1
≥2i+1,可以得到上述形态
然后开个数组维护就好了
优美,极简,是我心中代码的样子
#include<bits/stdc++.h>
using namespace std;
#define in Read()
int in{
int i=0,f=1;char ch=0;
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') ch=getchar(),f=-1;
while(isdigit(ch)) i=(i<<3)+(i<<1)+ch-48,ch=getchar();
return i*f;
}
const int mod=1e9+7,N=2e5+5;
int n,a[N],cnt,ans=1,sta[N];
int mul(int a,int b){return 1ll*a*b%mod;}
int main(){
n=in;
for(int i=1;i<=n;++i) a[i]=in;
sort(a+1,a+n+1);
for(int i=1;i<=n;++i){
if(a[i]==cnt*2) ans=mul(ans,cnt+1);
else sta[++cnt]=cnt*2-1;
}
while(cnt){
ans=mul(ans,cnt);
--cnt;
}
printf("%d\n",ans);
return 0;
}