小记:这次大赛教训惨重,ACM的路任重道远,现在努力做出每道题的解题报告吧。以此来抚慰我那惨痛的心灵。
题目:
这个题目名叫So easy! 当初看了 就想A, 现在看来这估计就是个陷阱,数学不好的必被坑。
由于我是用word写好的,但是里面的数学符号复制不出来,所以我就用图片来描述好了。
Solution
递推求通项公式的特征根的方法可以看这个:
http://sx.fjjcjy.com/upLoad/news/month_1203/201203091236588965.doc(这是的文件,点击就直接下载了)
(之前没A之前,犯了右乘和左乘的理解错误,改过来就差不多了,之前的代码提交的错了,除了左乘和右乘理解错误外,还有就是没有将进行快速幂的矩阵里的负元素变成正数(通过加M,即要取模的值变成正数,如果有负数的话,进行快速幂是错的),全改了之后就A了。)(6.1 修改)
在快速幂的时候就进行取模运算,防溢出。
进过转换之后,我们发现这题纯粹就是一道简单的矩阵快速幂的模板题。顿时觉得数学是门非常深奥的课程,需要不断的去学习探索。败在这题之下,确实只能怪自己基础不扎
实,受教了。模板我的博客里有。
这题,经过几天的思考,在wuzhengkai大神的点拨下,以及另一位神犇(链接没找到)的帮助下,顿悟了。在此特地感谢!
//下面贴上我的代码,湖大OJ 暂时打不开,所以还不知道正确与否,不过根据我自己生成的随机数据,理论上应该没错。
下面是错误的代码:
#include <iostream>
#include <stdio.h>
using namespace std;
#define N 2
#define ll unsigned long long
struct Matrix {
ll v[N][N];
};
Matrix A,B={1,0,0,1};
ll M;
Matrix mul(Matrix m1,Matrix m2,ll M){
int i,j,k;
Matrix c;
for(i=0;i<N;i++)for(j=0;j<N;j++){
c.v[i][j]=0;
for(k=0;k<N;k++)
c.v[i][j]+=(m1.v[i][k]*m2.v[k][j])%M;
c.v[i][j] %= M;
}
return c;
}
Matrix Mpow(Matrix A,Matrix B,ll n,ll M){
Matrix x=A,c=B;
while(n>=1){
if(n&1)c=mul(c,x,M);
n>>=1;
x=mul(x,x,M);
}
return c;
}
int main() {
//freopen("d:\\in.txt","r",stdin);
//freopen("d:\\out.txt","w",stdout);
//int flag = 0;
ll n, a, b;
while(cin>>a>>b>>n>>M){
/*if(flag)cout << endl;
else flag = 1;*/
if(n == 1){
cout << (2*a) % M <<endl;continue;
}
if(n == 2){
cout << (2*a*a + 2*b) % M <<endl;continue;
}
A.v[0][0] = 2*a;
A.v[0][1] = b - a*a ;
A.v[1][0] = 1;
A.v[1][1] = 0;
Matrix p = Mpow(A,B,n-2,M), q = {2*a*a + 2*b, 0, 2*a, 0};
p = mul(p,q,M);
cout<<p.v[0][0]<<endl;
}
return 0;
}
改正后的A过的代码:(6.1修改)
#include <iostream>
#include <stdio.h>
using namespace std;
#define N 2
#define ll long long
struct Matrix {
ll v[N][N];
};
Matrix A,B={1L,0L,0L,1L};
ll M;
Matrix mul(Matrix m1,Matrix m2,ll M){
int i,j,k;
Matrix c;
for(i = 0; i < N; i++)
for(j = 0; j < N; j++){
c.v[i][j] = 0;
for(k = 0; k < N; k++){
c.v[i][j] += (m1.v[i][k]*m2.v[k][j])%M;
c.v[i][j] %= M;
}
c.v[i][j] %= M;
}
return c;
}
Matrix Mpow(Matrix A,Matrix B,ll n,ll M){
Matrix x = A,c = B;
while(n >= 1){
if(n&1L)c = mul(c,x,M);
n >>= 1;
x = mul(x,x,M);
}
return c;
}
int main() {
//freopen("F:\\problem A\\in.txt","r",stdin);
//freopen("F:\\problem A\\out.txt","w",stdout);
ll n, a, b, t;
while(cin>>a>>b>>n>>M){
if(n == 1){
cout << (2*(a%M)) % M <<endl;continue;
}
if(n == 2){
cout << ((2*((a%M)*(a%M))%M)%M + (2*b)%M) % M <<endl;continue;
}
A.v[0][0] = (2*(a%M)) % M;
t = a;
t *= a;
A.v[0][1] = 1;
t = b - t;
while(t < 0)t += M;
A.v[1][0] = t;
A.v[1][1] = 0;
Matrix p = Mpow(A,B,n-2,M), q = {((2*((a%M)*(a%M))%M)%M + (2*b)%M) % M, (2*(a%M)) % M, 0L, 0L};
p = mul(q,p,M);
cout<<p.v[0][0]<<endl;
}
return 0;
}