热身题(高斯消元)

热身题(j.cpp/c/pas)

时间限制:1s

空间限制:128M

输入文件:j.in

输出文件:j.out

 

【问题描述】

定义F:

F(1) = 1,

F(2) = 2,

F(n) = F(n-1) + F(n-2) (n >= 3)

定义p:

p(i) = a1*F(1)^i + a2*F(2)^i + … + ak*F(k)^i

其中k和a1…ak为常数。

现在已知k,p(1),p(2),…,p(k),求p(k+1)。为了避免高精度,所有运算都模掉M。保证F(1),…,F(n)在模质数M下两两不同,保证有唯一解。

【输入格式】

第一行,两个整数k,M。

第二行,p(1), p(2), . . . , p(k) 模 M 。

【输出格式】

输出p(k+1)模M。

【样例输入1】

3 101

5 11 29

【样例输出1】

83

【样例输入2】

4 619

5 25 125 6

【样例输出2】

30

【数据规模与约定】

对于20%的数据,k<=10

对于50%的数据,k<=100

对于100%的数据,1<=k<=4000, 3<=M<=10^9

 

题解

50分是裸高斯消元

lazycal:

F1   F2   … Fk

F1^2 F2^2 … Fk^2

F1^3 F2^3 … Fk^3

F1^4 F2^4 … Fk^4

F1^k F2^k … Fk^k

可以发现系数是有规律的。我们可以用第i行减掉第i-1行*F1,这样就可以将第1列中除了第1行的数清零。同理第2列,第3列。。。这样就可以得到一个上三角矩阵。而且第i行第j列的数为Fj*(Fj-F1)*(Fj-F2)*…*(Fj-Fi-1)。然后就可以解出a1…ak。然后算出Fk+1,得到答案。

上述做法常数实现的好的话应该可以过。

但是这题毕竟不需要求出a1…ak,所以我们可以将第k+1个方程写在最下方,也参与消元。最终最后一个方程的系数都被消为0,此时等号右边的值即为答案。

#include <cstring>
#include <iostream>
#include <cmath>
#include <cstdio>

using namespace std;
typedef long long LL;

#define N 4004

void read(LL &x) {
	char c;bool flag = 0;
	while((c=getchar())<'0'||c>'9') flag |= (c=='-');
	x=c-'0';while((c=getchar())>='0'&&c<='9') x=x*10+c-'0';
	if(flag) x = -x;
}

LL n,m,a[N],f[N];

LL Mod(LL x) {return ((x%m)+m)%m;}

int main() {
	//freopen("j.in","r",stdin);freopen("j.out","w",stdout);
	read(n); read(m);
	f[1] = 1; f[2] = 2;
	for (int i = 3; i <= n+1; i++) f[i] = (f[i-1]+f[i-2])%m;
	for (int i = 1; i <= n; i++) read(a[i]);
    for (int i = 1; i <= n; i++)
	 for (int j = n+1; j > i; j--)
	   a[j] = Mod(a[j]-a[j-1]*f[i]);
	printf("%lld",Mod(-a[n+1]));
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值