题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6198
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Problem Description
We define a sequence :
Give you an integer , if a positive number can be expressed by
where , this positive number is . Otherwise, this positive number is .
Now, give you an integer , you task is to find the minimal positive number.
The answer may be too large. Please print the answer modulo 998244353.
Input
There are about 500 test cases, end up with EOF.
Each test case includes an integer which is described above. ()
Output
For each case, output the minimal number mod 998244353.
Sample Input
1
Sample Output
4
Problem solving report:
Description: 给你一段斐波那契数列,有个关于mif-good的定义,就是给你一个k,如果对于一个n,能由k项斐波那契数相加来表示,那么这个数就叫mif-good,否则就是mif-bad,现在输入k,让你求最小的mif-bad.
Problem solving: 我们令G(k)表示上述表达的最小的mif-bad数,通过打表我们可以发现G(n)-G(n-1)=F(2n+2),那么我们就可以通过求前缀和求出G(n):
对上式相加可得到:
故我们只需要求出F(2*n+3)-1就行了。因为数据过大我们需要矩阵加速。
Accepted Code:
/*
* @Author: lzyws739307453
* @Language: C++
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MOD = 998244353;
struct Mat {
ll m[3][3];
Mat() {
memset(m, 0, sizeof(m));
}
}ans, a;
Mat Mul(Mat a, Mat b) {
Mat c;
for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
for (int k = 0; k < 2; k++)
c.m[i][j] = (c.m[i][j] + (a.m[i][k] * b.m[k][j]) % MOD) % MOD;
return c;
}
Mat power(Mat a, int k) {
Mat p;
p.m[0][0] = 1, p.m[1][1] = 1;
while (k) {
if (k & 1)
p = Mul(p, a);
a = Mul(a, a);
k >>= 1;
}
return p;
}
int main() {
int n;
while (~scanf("%d", &n)) {
int k = 2 * n + 3;
a.m[0][0] = 1, a.m[0][1] = 1;
a.m[1][0] = 1, a.m[1][1] = 0;
ans.m[0][0] = 1, ans.m[0][1] = 0;
ans = Mul(ans, power(a, k - 1));
printf("%lld\n", (ans.m[0][0] - 1 + MOD) % MOD);
}
return 0;
}
打表Code:
/*
* @Author: lzyws739307453
* @Language: C++
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll F[1005];
int dp[200][2005];
int main() {
F[0] = 0, F[1] = 1, F[2] = 1;
for (int i = 2; i < 1000; i++)
F[i] = F[i - 1] + F[i - 2];
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;
for (int i = 0; i <= 45; i++)//枚举总类
for (int j = 1; j <= 50; j++) //枚举个数
for (ll k = F[i]; k <= 1000; k++) //枚举容量
dp[j][k] += dp[j - 1][k - F[i]];
for (int i = 0; i <= 40; i++)
for (int j = 1; j <= 1000; j++)
if (!dp[i][j]) {
printf("%d %d\n", i, j);
break;
}
printf("**************\n");
for (int i = 0; i < 20; i++)
printf("%d %d\n", i, F[i]);
return 0;
}