您的位置:首页 > 其它

【HDU6198 2017 ACM ICPC Asia Regional Shenyang Online E】【找规律 + 矩阵快速幂 + 粗略证明】number number number 无法用K

2017-09-11 11:17 447 查看


number number number

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 235    Accepted Submission(s): 151


Problem Description

We define a sequence F:

⋅ F0=0,F1=1;
⋅ Fn=Fn−1+Fn−2 (n≥2).

Give you an integer k,
if a positive number n can
be expressed by
n=Fa1+Fa2+...+Fak where 0≤a1≤a2≤⋯≤ak,
this positive number is mjf−good.
Otherwise, this positive number is mjf−bad.

Now, give you an integer k,
you task is to find the minimal positive mjf−bad 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 k which
is described above. (1≤k≤109)

 

Output

For each case, output the minimal mjf−bad number
mod 998244353.

 

Sample Input

1

 

Sample Output

4

 

Source

2017 ACM/ICPC Asia Regional Shenyang Online

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
#define MS(x, y) memset(x, y, sizeof(x))
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
const int N = 1010, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;
template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
int casenum, casei;
int K;
int fib
;
bitset<100010>f[24];
void table()
{
fib[0] = 0; fib[1] = 1;
for (int i = 2; i <= 30; ++i)
{
fib[i] = fib[i - 1] + fib[i - 2];
}
f[0][0] = 1;
for (int i = 0; i <= 20; ++i)
{
for (int k = 0; k <= 30; ++k)
{
f[i + 1] |= (f[i] << fib[k]);
}
for (int j = 1; j < 100000; ++j)if (!f[i][j])
{
printf("%d %d\n", i, j);
break;
}
}
}
namespace FAST_MATRIX
{
#define rep(i) for(int i = 0; i < G; ++i)
#define matrix0(a) rep(i)rep(j)a[i][j] = 0;

const int G = 2;
int a[G][G], b[G][G], c[G][G];
void mul(int a[][G], int b[][G], int c[][G])
{
static int tmp[G][G];
matrix0(tmp);
rep(i)rep(j)rep(k)tmp[i][j] = (tmp[i][j] + (LL)a[i][k] * b[k][j]) % Z;
rep(i)rep(j)c[i][j] = tmp[i][j];
}
void qpow(int x[][G], int y[][G], LL p)
{
matrix0(y);
rep(i)y[i][i] = 1;
while (p)
{
if (p & 1)
mul(x, y, y);
mul(x, x, x);
p >>= 1;
}
}
void solve(int K)
{
matrix0(a); a[0][1] = 1;
b[0][0] = 0; b[0][1] = 1;
b[1][0] = 1; b[1][1] = 1;

qpow(b, c, K * 2 + 3);
mul(a, c, b);
printf("%d\n", (b[0][0] + Z - 1) % Z);
}
}
int main()
{
//table();
while(~scanf("%d", &K))
{
FAST_MATRIX::solve(K);
//printf("%d\n", DU::solve(K));
}
return 0;
}

/*
【trick&&吐槽】
找规律要不一定要盲目做,可以适当考虑结合其它数列一起做考虑。

【题意】
输入一个K(1e9)范围的数,让你求出,无法用K个斐波那契数表示的最小整数。

【分析】
这道题打表可以发现前几项的答案是

项数 0 1 2 3 4 5 6 7
1 4 12 33 88 232 609

但是只从这些数上找递推关系好难啊。
郑经诗这次发现规律好快呀——我们只要与斐波那契数列一起考虑就好啦!

斐波那契 0 1 1 2 3 5 8 13 21 34 55 89
发现没有?ans[i] = fib[i * 2 + 3] - 1

于是一个矩阵快速幂就可以解决这道题。
输入K,则求fib[K * 2 + 3]

============================================================
fibonacci 矩阵
初始态a:
[0 1]
转移态b:
[0 1]
[1 1]
最终:
c = a * (b ^ (K * 2 + 3))
c.v[0][0]就是答案
============================================================
证明——
我们再考虑一下这道题的证明:
假如说,我们用K个数不构成的最小整数为X,且X = fib[x] - 1
并且有fib[x] + fib[y] = fib[z]

那么现在有了第K+1个斐波那契数,我们要证明[1, fib[z] - 2]的正整数都可以构成,而fib[z] - 1恰好不行。
因为[1, fib[x] - 2]都可以构成呀,所以加上fib[y],显然[1, fib[z] - 2]都可以构成。
那么,为什么fib[z] - 1构成不了呢?

1,如果选了fib[y],则因为其他K个数构不成fib[x] - 1,于是整体上无法构成fib[z] - 1
2,如果不选fib[y](即不选f[z-1]),
我们发现——
要至少使用K+1个数才能构成fib[z-1] - 1
fib[z-1] - 1 + f[z-1] == f[z],这里至少要还要一个f[z-1],但是已经说了不取了,而f[z-1]要至少2个数,GG
要至少使用K-1个数才能构成fib[z-2] - 1
fib[z-2] - 1 + f[z-2]+f[z-2] == f[z],这里至少要还要两个f[z-2],但是已经说了不取了,而构成一个f[z-2]要也至少2个数,GG
要至少使用K-2个数才能构成fib[z-3] - 1
fib[z-3] - 1 + f[z-3]+f[z-3]+... == f[z],发现数量依然是不够的。总之,就GG了……

【时间复杂度&&优化】
O(8 * log(K))

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐