题目大意
有无穷多个边长为 \(1\) 的正方形和边长为 \(1\) 的正三角形,问一共有多少种不同的方式,能够拼出一个边长为 \(n\) 的正十二边形。要求使用的图形不能重叠,也不能存在空缺。 \(n\le 10^6\),输出答案除以 \(998244353\) 的余数。
题目解析
显然我们发现当 \(n=1\) 的时候显然答案为 \(1\),这里放一张图片供参考。
不难发现正十二边形的每一个内角都是 \(\frac{5}{6}\pi=\frac{1}{2}\pi+\frac{1}{3}\pi\) ,恰好是一个正方形和一个正三角形的内角和,所以说我们必须在一条个角使用一个正方形和正三角形。不难发现如果每一条边上只要有一个图形是正三角形或者是正方形,那么这条边上全是正三角形或者是正方形。我们发现如果一条边上放了正方形,这条边的长度不变;如果这条边放了三角形,那么这条边的长度就会减去 \(1\) 。当有一条边的长度减成 \(0\) 的时候,那么这个图形就是一个六边形,就只能全部用三角形填充了,只有 \(1\) 种方案。
不妨设 \(f_{i,j}\) 是一条边长为 \(i\),另一条边为 \(j\) 的方案数,不难得出:
我们发现,这不就是杨辉三角吗?然后我们发现我们不难找到通项公式:
\[f_{i,j}=C^(i)_{i+j} \]由于可以通过旋转将一些方案重合,所以最终的答案应该是: $$\frac{1}{2}f_{n,n}=\frac{\left(2n\right)!}{2\times n! \times n!}$$
贴一个代码:
#include<cstdio>
#define I inline
#define db double
#define U unsigned
#define Re register
#define ll long long
#define RI register int
#define ull unsigned long long
#define swap(x,y) x^=y^=x^=y;
#define abs(x) ((x)>0?(x):(-(x)))
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define Me(a,b) memset(a,b,sizeof(a))
#define EPS (1e-7)
#define INF (0x7fffffff)
#define LL_INF (0x7fffffffffffffff)
#define MOD 998244353
//#define debug
using namespace std;
#define Type int
I Type read(){
Type sum=0; int flag=0; char c=getchar();
while((c<'0'||c>'9')&&c!='-') c=getchar(); if(c=='-') c=getchar(),flag=1;
while('0'<=c&&c<='9'){ sum=(sum<<1)+(sum<<3)+(c^48); c=getchar(); }
if(flag) return -sum; return sum;
}
ll fact,inv,n;
const ll Half=499122177;
ll js(ll x){ ll res=1; for(RI i=1;i<=x;i++) res=res*i%MOD; return res; }
ll pow(ll x,ll y){ ll res=1,tmp=x; while(y){ if(y&1) res=res*tmp%MOD; tmp=tmp*tmp%MOD; y>>=1; } return res; }
int main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
n=read(); fact=js(n<<1); inv=pow(js(n),MOD-2); printf("%lld",Half*fact%MOD*inv%MOD*inv%MOD);
return 0;
}