您的位置:首页 > 其它

51nod - 1573 分解 - 矩阵快速幂

2016-08-31 14:01 302 查看
51nod 算法马拉松17(告别奥运)B 分解 51nod 算法马拉松17(告别奥运)B 分解

题意 :给出一个n,问(1+2√)n 能否拆成m−−√+m−1−−−−−√ 的形式,如果能,输出m,否则输出 no。

想法

观察(1+2√)n,它总能写成a+b2√的形式,如果a2n=m,2∗b2n=m−1 或者a2n=m−1,2∗b2n=m,那就可以了。 于是我们设(1+2√)n=an+bn2√,不难找到(anbn)=(a1b1)(1211)n−1

#include<bits/stdc++.h>
using namespace std;
const int maxn = 105;
const int mod = 1e9 + 7;
int t = 2;
struct mat
{
long long v[maxn][maxn];
int n;
void clear()
{
n = t;
memset(v, 0, sizeof(v));
}
void unit()
{
clear();
for(int i=0; i<n; i++)
v[i][i] = 1;
}
void fro()
{
clear();
v[0][1] = v[1][0] = v[1][1] = 1;
}
void print()
{
for(int i=0; i<n; i++)
{
cout << v[i][0];
for(int j=1; j<n; j++)
cout << " " << v[i][j];
cout << endl;
}
}

};
mat operator * (const mat a, const mat b)
{
mat res;
res.clear();
for(int i=0; i<t; i++)
{
for(int j=0; j<t; j++)
{
for(int k=0; k<t; k++)
{
res.v[i][j] = (res.v[i][j] + a.v[i][k] * b.v[k][j]) % mod;
}
}
}
return res;
}
mat operator ^ (mat a, long long b)
{
mat r , base = a;
r.unit();
while(b)
{
if(b&1)
r = r * base;
base = base * base;
b >>= 1;
}
return r;
}
int main()
{
long long m;
mat a;
a.clear();
a.v[0][0] = 1, a.v[0][1] = 1;
a.v[1][0] = 2, a.v[1][1] = 1;
cin >> m;
if(m == 0) {
cout << 1 << endl; return 0;
} else if(m == 1) {
cout << 2 << endl; return 0;
}
a = (a^(m-1));
long long t = a.v[0][0] + a.v[1][0];
long long s = a.v[0][1] + a.v[1][1];
long long tm = (t % mod) * (t % mod) % mod;
long long sm = ((s % mod) * (s % mod) * 2 + 1 )% mod;
long long ms = ((s % mod) * (s % mod) * 2 - 1 + mod)% mod;
if(tm == sm)
cout << tm << endl;
else if(tm == ms)
cout << (tm + 1 + mod) % mod << endl;
else
cout << "no" << endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  矩阵 51nod ACM