【NOI2022省选挑战赛 Contest10 A】多项式求根(矩阵乘法)

多项式求根

题目链接:NOI2022省选挑战赛 Contest10 A

题目大意

给你 x+y,xy % 998244343 的值,要你求 x^n+y^n % 998244353 的值。

思路

考虑从 \(x^{n-1}+y^{n-1}\) 推出 \(x^n+y^n\)
\((x^{n-1}+y^{n-1})(x+y)=x^n+x^{n-1}y+y^{n-1}x+y^n\)
\((x^{n-1}+y^{n-1})(x+y)=x^n+y^n+xy(x^{n-2}+y^{n-2})\)
\(x^n+y^n=(x^{n-1}+y^{n-1})(x+y)-xy(x^{n-2}+y^{n-2})\)
\(x^i+y^i=f_i,(x+y)=a,xy=b\)
\(f_n=af_{n-1}-bf_{n-2}\)

然后就可以用矩阵乘法来做啦!

代码

#include<cstdio>
#define ll long long
#define mo 998244353

using namespace std;

ll a, b, n;
struct matrix {
	ll n, m, a[3][3];
}A, B, C, one;

matrix operator *(matrix x, matrix y) {
	matrix re;
	re.n = x.n; re.m = y.m;
	for (int i = 1; i <= re.n; i++)
		for (int j = 1; j <= re.m; j++)
			re.a[i][j] = 0;
	for (int k = 1; k <= x.m; k++)
		for (int i = 1; i <= re.n; i++)
			for (int j = 1; j <= re.m; j++)
				(re.a[i][j] += x.a[i][k] * y.a[k][j] % mo) %= mo;
	return re;
}

matrix jcksm(matrix x, ll y) {
	matrix re = one;
	while (y) {
		if (y & 1) re = re * x;
		x = x * x; y >>= 1;
	}
	return re;
}

int main() {
	scanf("%lld %lld %lld", &a, &b, &n);
	
	A.n = 1; A.m = 2;
	A.a[1][1] = 2; A.a[1][2] = a;
	B.n = 2; B.m = 2;
	B.a[1][1] = 0; B.a[1][2] = mo - b;
	B.a[2][1] = 1; B.a[2][2] = a;
	one.n = 2; one.m = 2;
	one.a[1][1] = 1; one.a[1][2] = 0;
	one.a[2][1] = 0; one.a[2][2] = 1;
	C = jcksm(B, n - 1);
	
	A = A * C;
	printf("%lld", A.a[1][2]);
	
	return 0;
}
posted @ 2022-03-21 19:44  あおいSakura  阅读(72)  评论(0)    收藏  举报