Description
nodgd 要画一个电路图。
这是一个很简单的电路图,所有的元件都是串联关系,从整体来看就是一个环状的结构。画电路图有很多要求,nodgd 为了画得好看就又添加了一些
额外的要求。所有要求归结起来有以下几点:
1、这个环状电路上有n个双端电路元件(即每个电路元件有两个连接导线的接头),其中只有一个直流电源;为了本题方便,其他n − 1个元件都是一模一样的电阻。
2、电流在电路图中每经过一个元件,就必须拐一个90°的弯;没有经过元件时不允许拐弯。参考右图。
3、从电路图整体上观察,电流沿顺时针方向流动,且电路不能自交。参考下图。
4、如果一个符合题意的电路图,可以通过整体旋转一定的角度,再适当调整图中导线的长度,得到另外一个符合题意的电路图,则这两个电路图是相同的。参考下图。
5、如果电路环路的内部存在一个点,使得它可以“看到”电路环路内部的所有位置,就认为这个图是美观的,反之是不美观的。相同的电路图不一定都美观。参考下图。
那么问题来了,nodgd 想知道有多少种不同的电路图,以及有多少种不同的美观电路图。由于两个问题的答案都可能很大,请mod 1,000,000,007输出结果。
Input
输入文件 A.in。
输入文件第一行包含一个正整数n,表示包含电源在内的电路元件的总数量。
Output
输出文件A.out。
输出文件第一行包含一个整数,表示不同的电路图数量mod 1,000,000,007的结果。第二行包含一个整数,表示不同的美观电路图数量mod 1,000,000,007的结果。
Sample Input
【样例1】
6
【样例2&3】见下发文件
Sample Output
【样例1】
6
6
Data Constraint
对于 10%的数据,n = 12;
对于 30%的数据,n ≤ 24;
对于 60%的数据,n ≤ 5000;
对于 100%的数据,4 ≤ n ≤ 10^7,且n是个偶数。
Hint
【输入输出样例 1 说明】
可以有如下几种电路图,电路图数量是 6,所以输出文件第一行输出一个整数 6; 容易发现,这 6 个电路图都是美观的电路图,所以第二行也输出一个整数 6。
Solution
-
结论题。
-
有一个元件就会拐弯一次,我们发现 右拐次数就等于左拐次数+4 ,因为要顺时针拐一圈回来。
-
所以第一问的答案即为 C n n / 2 − 2 C_{n}^{n/2-2} Cnn/2−2 ,即从 n n n 次拐弯中选 n / 2 − 2 n/2-2 n/2−2 次左拐。
-
第二问的话我们发现不能连续两次逆时针拐弯,不然就会形成一个不美观的凹型。
-
所以我们把路径分成四段,可以发现每段的拐弯数都是奇数。
-
问题转化为将 n n n 拆分成 4 个奇数的方案数( n n n 是偶数)。
-
我们先考虑将 n n n 拆成 4 个偶数怎么做。将 n / 2 − 1 n/2-1 n/2−1 个偶数排在一起(都小于 n n n)。
-
选 3 个出来(相当于挡板),将间隔作为选择的偶数(保证了和不会超过 n n n)。
-
于是我们就可以得出方案书为 C n / 2 − 1 3 C_{n/2-1}^{3} Cn/2−13 。
-
类比选 4 个奇数,我们将这四个奇数都加 1 ,则和为 n + 4 n+4 n+4 。
-
于是方案数为 C ( n + 4 ) / 2 − 1 3 = C n / 2 + 1 3 C_{(n+4)/2-1}^{3}=C_{n/2+1}^{3} C(n+4)/2−13=Cn/2+13
-
由于电源放在哪儿都可以,所以要乘 n n n ;
-
又因为整体旋转后相同的电路图都是一样的,所以要除以 4 。
-
故第二问最终答案为 C n / 2 + 1 3 ∗ n / 4 C_{n/2+1}^{3}*n/4 Cn/2+13∗n/4 。
Code
#include<cstdio>
using namespace std;
typedef long long LL;
const int N=1e7+5,mo=1e9+7;
int n;
int f[N];
inline int ksm(int x,int y)
{
int s=1;
while(y)
{
if(y&1) s=(LL)s*x%mo;
x=(LL)x*x%mo;
y>>=1;
}
return s;
}
inline int C(int x,int y)
{
return (LL)f[x]*ksm(f[y],mo-2)%mo*ksm(f[x-y],mo-2)%mo;
}
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
scanf("%d",&n);
for(int i=f[0]=1;i<=n;i++) f[i]=(LL)f[i-1]*i%mo;
printf("%d\n",C(n,n/2-2));
printf("%d",(LL)C(n/2+1,3)*n%mo*ksm(4,mo-2)%mo);
return 0;
}