您的位置:首页 > 其它

noip模拟赛 残

2017-10-22 21:06 211 查看


分析:这道题有点丧病啊......斐波那契数列本来增长就快,n <= 10^100又套2层,看到题目就让人绝望.不过这种题目还是有套路的.首先求斐波那契数列肯定要用到矩阵快速幂,外层的f可以通过取模来变小,可是里面的f不能直接取模1e9+7.因为余数最多就1e9+7种,所以肯定有一个循环节,打表发现内层f的循环节是2000000016,x的循环节是(1e9+7)*3,在求得时候mod循环节长度就ok了.

关于斐波那契的一些套路要记住:用矩阵快速幂加速、有循环节......

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

const long long mod = 1000000007;
const long long mod2 = mod * 2 + 2;
const long long mod3 = mod2 * 3;

typedef long long ll;

int T, len, shu[210];
char s[210];
ll t;

struct node
{
ll a[3][3];
node(){ memset(a, 0, sizeof(a)); }
}x, y;

ll zhuanhuan()
{
ll res = 0;
for (int i = 1; i <= len; i++)
shu[i] = s[i] - '0';
for (int i = 1; i <= len; i++)
res = (res * 10 + shu[i]) % mod3;
return res;
}

node mul1(node x, node y)
{
node p;
memset(p.a, 0, sizeof(p.a));
for (int i = 1; i <= 2; i++)
for (int j = 1; j <= 2; j++)
for (int k = 1; k <= 2; k++)
p.a[i][j] = (p.a[i][j] + x.a[i][k] * y.a[k][j] % mod2) % mod2;
return p;
}

node mul2(node x, node y)
{
node p;
memset(p.a, 0, sizeof(p.a));
for (int i = 1; i <= 2; i++)
for (int j = 1; j <= 2; j++)
for (int k = 1; k <= 2; k++)
p.a[i][j] = (p.a[i][j] + x.a[i][k] * y.a[k][j] % mod) % mod;
return p;
}

ll qpow1(ll b)
{
x.a[1][1] = 0;
x.a[1][2] = 1;
y.a[1][1] = 0;
y.a[1][2] = y.a[2][1] = y.a[2][2] = 1;
while (b)
{
if (b & 1)
x = mul1(x, y);
y = mul1(y, y);
b >>= 1;
}
return x.a[1][1];
}

ll qpow2(ll b)
{
x.a[1][1] = 0;
x.a[1][2] = 1;
y.a[1][1] = 0;
y.a[1][2] = y.a[2][1] = y.a[2][2] = 1;
while (b)
{
if (b & 1)
x = mul2(x, y);
y = mul2(y, y);
b >>= 1;
}
return x.a[1][1];
}

int main()
{
scanf("%d", &T);
while (T--)
{
scanf("%s", s + 1);
len = strlen(s + 1);
t = zhuanhuan();
t = qpow1(t);
printf("%lld\n", qpow2(t));
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: