JZOJ 5878. 【NOIP2018提高组模拟9.22】电路图 A

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liyizhixl/article/details/82820452

Description

nodgd 要画一个电路图。
这是一个很简单的电路图,所有的元件都是串联关系,从整体来看就是一个环状的结构。画电路图有很多要求,nodgd 为了画得好看就又添加了一些
额外的要求。所有要求归结起来有以下几点:
1、这个环状电路上有n个双端电路元件(即每个电路元件有两个连接导线的接头),其中只有一个直流电源;为了本题方便,其他n − 1个元件都是一模一样的电阻。
2、电流在电路图中每经过一个元件,就必须拐一个90°的弯;没有经过元件时不允许拐弯。参考右图。

Description

3、从电路图整体上观察,电流沿顺时针方向流动,且电路不能自交。参考下图。

Description

4、如果一个符合题意的电路图,可以通过整体旋转一定的角度,再适当调整图中导线的长度,得到另外一个符合题意的电路图,则这两个电路图是相同的。参考下图。

Description

5、如果电路环路的内部存在一个点,使得它可以“看到”电路环路内部的所有位置,就认为这个图是美观的,反之是不美观的。相同的电路图不一定都美观。参考下图。

Description

那么问题来了,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。

Hint

Solution

  • 结论题。

  • 有一个元件就会拐弯一次,我们发现 右拐次数就等于左拐次数+4 ,因为要顺时针拐一圈回来。

  • 所以第一问的答案即为 C n n / 2 2 C_{n}^{n/2-2} ,即从 n n 次拐弯中选 n / 2 2 n/2-2 次左拐。

  • 第二问的话我们发现不能连续两次逆时针拐弯,不然就会形成一个不美观的凹型。

  • 所以我们把路径分成四段,可以发现每段的拐弯数都是奇数。

  • 问题转化为将 n n 拆分成 4 个奇数的方案数( n n 是偶数)。

  • 我们先考虑将 n n 拆成 4 个偶数怎么做。将 n / 2 1 n/2-1 个偶数排在一起(都小于 n n )。

  • 选 3 个出来(相当于挡板),将间隔作为选择的偶数(保证了和不会超过 n n )。

  • 于是我们就可以得出方案书为 C n / 2 1 3 C_{n/2-1}^{3}

  • 类比选 4 个奇数,我们将这四个奇数都加 1 ,则和为 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}

  • 由于电源放在哪儿都可以,所以要乘 n n

  • 又因为整体旋转后相同的电路图都是一样的,所以要除以 4 。

  • 故第二问最终答案为 C n / 2 + 1 3 n / 4 C_{n/2+1}^{3}*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;
}

猜你喜欢

转载自blog.csdn.net/liyizhixl/article/details/82820452