组合数问题(复数快速幂, 组合数)

牛客
在这里插入图片描述

思路
参考题解, 众所周知组合数是满足二项式定理的, 这里有:
( x + y ) n = C n 0 x 0 y n + C n 1 x y n − 1 + . . . + C n n − 1 x n − 1 y + C n n x n y 0 ( x + y )^n = C _n^0 x_0 y _n + C _n^ 1 x y^ {n − 1} + . . . + C _n ^{n − 1} x_ {n − 1} y + C_ n^ n x _n y _0 (x+y)n=Cn0x0yn+Cn1xyn1+...+Cnn1xn1y+Cnnxny0
考虑复数有
i 1 = i i^1=i i1=i
i 2 = − 1 i ^2 = − 1 i2=1
i 3 = − i i^3=-i i3=i
i 4 = 1 i^4 = 1 i4=1
因此当 x = 1 , y = − i x =1, y = -i x=1,y=i,该二项式为:
( 1 + i ) n = C n 0 i n + C n 1 i n − 1 + C n 2 i n − 2 + C n 3 i n − 3 + . . . + C n n − 1 i + C n n i 0 (1 + i)^n = C_n^0i^{n} + C_n^1i^{n-1} +C_n^2i^{n-2} +C_n^3i^{n-3} +... + C_n^{n-1}i + C_n^ni^0 1+i)n=Cn0in+Cn1in1+Cn2in2+Cn3in3+...+Cnn1i+Cnni0
x = 1 , y = − i x = 1, y = -i x=1,y=i,该二项式为
( 1 − i ) n = C n 0 ( − i ) n + C n 1 ( − i ) n − 1 + C n 2 ( − i ) n − 2 + C n 3 ( − i ) n − 3 + . . . + C n n − 1 ( − i ) + C n n ( − i ) 0 = ( 1 + i ) n    =    C n 0 i n − C n 1 i n − 1 + C n 2 i n − 2 − C n 3 i n − 3 + . . . − C n n − 1 i + C n n i 0 (1 - i)^n = C_n^0(-i)^{n} + C_n^1(-i)^{n-1} +C_n^2(-i)^{n-2} +C_n^3(-i)^{n-3} +... + C_n^{n-1}(-i) + C_n^n(-i)^0 =(1 + i)^n ~~ =~~ C_n^0i^{n} - C_n^1i^{n-1} +C_n^2i^{n-2} -C_n^3i^{n-3} +... - C_n^{n-1}i + C_n^ni^0 (1i)n=Cn0(i)n+Cn1(i)n1+Cn2(i)n2+Cn3(i)n3+...+Cnn1(i)+Cnn(i)0=1+i)n  =  Cn0inCn1in1+Cn2in2Cn3in3+...Cnn1i+Cnni0

两者相加有
( 1 + i ) n + ( 1 − i ) n = 2 ( C n 0 − C n 2 + C n 4 − C n 6 + . . . + C n n ) (1 + i)^n + (1 - i)^n = 2(C_n^0 - C_n^2 + C_n^4 - C_n^6 +... + C_n^n) (1+i)n+(1i)n=2(Cn0Cn2+Cn4Cn6+...+Cnn)
( 1 + 1 ) n + ( 1 − 1 ) n = 2 ( C n 0 + C n 2 + C n 4 + C n 6 + . . . + C n n ) = 2 n (1 + 1)^n + (1 - 1)^n = 2(C_n^0 + C_n^2 + C_n^4 + C_n^6 +... + C_n^n)= 2^n (1+1)n+(11)n=2(Cn0+Cn2+Cn4+Cn6+...+Cnn)=2n

显然
2 n + ( 1 + i ) n + ( 1 − i ) n = 4 ∗ ( C n 0 + C n 4 + C n 8 + C n 12 + . . . . ) 2^n + (1 + i)^n + (1 - i)^n = 4 * (C_n^0 + C_n^4 + C_n^8 + C_n^{12} + ....) 2n+(1+i)n+(1i)n=4(Cn0+Cn4+Cn8+Cn12+....)
利用复数快速幂模板可以很快求解

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;

const int mod = 998244353;

typedef long long ll;
struct Complex {
	ll a, b; // a + bi
	Complex(ll _a, ll _b) {
		a = _a, b = _b;
	}
};

Complex mul(Complex A, Complex B) {
	ll a = ((A.a * B.a - A.b * B.b) % mod + mod) % mod;
	ll b = ((A.a * B.b + A.b * B.a) % mod + mod) % mod;
	return Complex(a, b); 
} 

Complex C_qp(Complex A, ll b) {
	Complex ans(1, 0);
	while(b) {
		if(b & 1) ans = mul(ans, A);
		A = mul(A, A);
		b >>= 1;
	}
	return ans;
}

ll qp(ll a, ll b) {
	ll ans = 1;
	while(b) {
		if(b & 1) ans = ans * a % mod;
		a = a * a % mod;
		b >>= 1;
	}
	return ans;
}

ll n;
int main()
{
	scanf("%lld", &n);
	ll res = qp(2, n);
	
	Complex A(1, 1);
	Complex B(1, -1);
	A = C_qp(A, n);
	B = C_qp(B, n);
	
	res = (res + A.a + B.a) % mod;
	res = res * qp(4, mod - 2) % mod;
	res = (res + mod) % mod;
	
	printf("%lld\n", res);
	
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值