吉比特2020春招题目(3.14),排列组合的题目,比较有意思。
题目这么讲:输入一个n(1<=n<=1e9),输出满足下列条件的序列个数
1)序列由A、B、C、D四个字母组成;
2)序列中A和C的个数和为偶数;
整个序列数比较庞大,最终结果输出为总序列数模1000000007后的值。
例:n=2时,序列数为8个,有BB、BD、DB、DD、AA、AC、CA、CC
输入数据
2
输出数据
8
多写几个n就会发现规律,序列分为两类:只由B、D两个字母组成的序列和包含A、C的序列。前一种序列数易得为2^n个。后面一个序列数比较难求,需要根据序列长度来判断。它可以被认为是选x个A或C(x为偶数,数量与前一种序列的序列数相同,都是2的n次方),以及n-x个第一种序列交叉组成而成。交叉方式相当于从n个位置中选择x种位置。
从上面的分析可以看出,两类序列其实符合同一种情况,总序列数可以由一个公式得到,即
2
n
∑
x
=
0
n
C
n
x
2^n\sum_{x=0}^nC_{n}^x
2n∑x=0nCnx(x为0到n的偶数)
上面公式可以看到,前一种序列只是后一种序列的特殊情况,即x=0或x=n(n为偶数)时候的情形。
#include <iostream>
using namespace std;
int main()
{
int i,j,n;
long long int sum1,sum2,mul;
while (cin>>n)
{
sum1=1;
for (i=0;i<n;i++)
sum1=(sum1*2)%1000000007;
sum2=0;
for (i=0;i<=n;i++)
{
if (!(i%2))
{
mul=1;
for (j=0;j<i;j++)
mul=(mul*(n-j)/(j+1))%1000000007;
sum2=(sum2+mul)%1000000007;
}
}
cout<<(sum1*sum2)%1000000007<<endl;
}
}
思考花的时间比较长,没来的及优化算法,n数字大于10000就超时了。