10229
题意:
给俩数n,m,求Fn mod (1 << m) 的值。
解析:
n达到了10^9,显然直接做是超时的。
考虑斐波那契数列的矩阵形式:
| Zn+1 | - | 0 1 | | Zn |
| Fn+1 | - | 1 1 | | Fn |
其中Z是增量,F是fib数列的第n项。
所以拆分成矩阵快速幂来做,只要计算矩阵系数的n次方,ans[ 0 ][ 1 ]就是答案。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <climits>
#include <cassert>
#define LL long long
using namespace std;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = 4 * atan(1.0);
const double ee = exp(1.0);
const int maxn = 30 + 10;
struct Matrax
{
LL num[maxn][maxn];
} a, per;
LL n, m, mod;
Matrax add(Matrax a, Matrax b)
{
Matrax c;
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
c.num[i][j] = (a.num[i][j] + b.num[i][j]) % mod;
}
}
return c;
}
Matrax multi(Matrax a, Matrax b)
{
Matrax c;
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
c.num[i][j] = 0;
for (int k = 0; k < 2; k++)
{
c.num[i][j] += a.num[i][k] * b.num[k][j];
}
c.num[i][j] %= mod;
}
}
return c;
}
Matrax power(LL k)
{
Matrax c, t;
Matrax res = per;
t = a;
while (k)
{
if (k & 1)
{
res = multi(res, t);
k--;
}
else
{
k >>= 1;
t = multi(t, t);
}
}
return res;
}
Matrax sum(LL k)
{
if (k == 1)
return a;
Matrax b, t;
t = sum(k >> 1);
if (k & 1)
{
b = power((k >> 1) + 1);
t = add(t, multi(t, b));
t = add(t, b);
}
else
{
b = power(k >> 1);
t = add(t, multi(t, b));
}
return t;
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCAL
while (scanf("%lld%lld", &n, &m) == 2)
{
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
per.num[i][j] = (i == j);
a.num[0][0] = 0; a.num[0][1] = 1;
a.num[1][0] = 1; a.num[1][1] = 1;
mod = 1LL << m;
Matrax ans = power(n);
printf("%lld\n", ans.num[0][1]);
}
return 0;
}
10518
题意:
求fib(n)被调用了多少次。
解析:
公式F(n) = 2 * fib(n) - 1
所以用矩阵快速幂求出fib(n),然后搞一搞就好了。
把n改成n+1, 结果(要 + mod) % mod
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <map>
#include <climits>
#include <cassert>
#define LL long long
using namespace std;
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const double pi = 4 * atan(1.0);
const double ee = exp(1.0);
const int maxn = 30 + 10;
struct Matrax
{
LL num[maxn][maxn];
} a, per;
LL n, b, mod;
Matrax add(Matrax a, Matrax b)
{
Matrax c;
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
c.num[i][j] = (a.num[i][j] + b.num[i][j]) % mod;
}
}
return c;
}
Matrax multi(Matrax a, Matrax b)
{
Matrax c;
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
c.num[i][j] = 0;
for (int k = 0; k < 2; k++)
{
c.num[i][j] += a.num[i][k] * b.num[k][j];
}
c.num[i][j] %= mod;
}
}
return c;
}
Matrax power(LL k)
{
Matrax c, t;
Matrax res = per;
t = a;
while (k)
{
if (k & 1)
{
res = multi(res, t);
k--;
}
else
{
k >>= 1;
t = multi(t, t);
}
}
return res;
}
Matrax sum(LL k)
{
if (k == 1)
return a;
Matrax b, t;
t = sum(k >> 1);
if (k & 1)
{
b = power((k >> 1) + 1);
t = add(t, multi(t, b));
t = add(t, b);
}
else
{
b = power(k >> 1);
t = add(t, multi(t, b));
}
return t;
}
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
#endif // LOCAL
int ca = 1;
while (scanf("%lld%lld", &n, &b) == 2)
{
if (!n && !b)
break;
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
per.num[i][j] = (i == j);
a.num[0][0] = 0; a.num[0][1] = 1;
a.num[1][0] = 1; a.num[1][1] = 1;
mod = b;
Matrax ans = power(n + 1);
// cout << ans.num[0][1] << endl;
printf("Case %d: %lld %lld %lld\n", ca++, n, b, (2 * ans.num[0][1] - 1 + mod) % mod);
}
return 0;
}