[HDU 5351 MZL's Border]
题意
定义字符串$f_1=b,f_2=a,f_i=f_{i-1}f_{i-2}$。
对$f_n$的长度为$m$的前缀$s$,
求最大的$k$满足$s[1]=s[m-k+1],s[2]=s[m-k+2]...s[k]=s[m]$
Solution
先列出前几个字符串
$f_3=ab,f_4=aba,f_5=abaab,f_6=abaababa,f_7=abaababaabaab$。
对于n,m。
假设$f_{n-1}$的长度大于等于$m$,那么相当于求n-1,m。
假设$f_{n-1}$的小于$m$
由斐波那契的性质,答案要么是$m-length(f_{n-1})$,
要么是$m-length(f_{n-2})$
通过对前几个字符串的分析可以发现,当$m+1<length(f_n)$时答案是后者。
于是只要先把前1000个字符串的长度求出来。需要使用高精度。
然后直接按照上面的规则判断就行了。
#include <bits/stdc++.h>
#define lson x << 1
#define rson x << 1 | 1
#define LL long long
#define se second
#define fi first
#define LL long long
using namespace std;
const int N = 1003;
string fib[N], m, ans;
inline string add ( string a, string b )
{
if ( a.size() < b.size() ) swap ( a, b );
int la = a.size(), lb = b.size(), x = 0, i = 0;
for ( i = 0; i < lb; ++i ) {
x += ( a[i] - '0' + b[i] - '0' );
a[i] = '0' + x % 10;
x /= 10;
}
while ( x && i < la ) {
x += ( a[i] - '0' );
a[i] = '0' + x % 10;
x /= 10;
++i;
}
if ( x ) a += '0' + x;
return a;
}
inline string sub ( string a, string b )
{
int la = a.size(), lb = b.size(), x = 0, i = 0;
for ( i = 0; i < lb; ++i ) {
if ( a[i] - x >= b[i] ) {
a[i] = a[i] - x - b[i] + '0';
x = 0;
} else {
a[i] = 10 + '0' + a[i] - b[i] - x;
x = 1;
}
}
while ( x && i < la ) {
if ( a[i] != '0' ) {
a[i] = a[i] - 1;
x = 0;
} else {
a[i] = '9';
++i;
}
}
i = la - 1;
while ( a[i] == '0' && i != 0 ) {
a.erase ( a.begin() + i );
--i;
}
return a;
}
int T, n;
inline bool pd ( string a, string b )
{
if ( a.size() == b.size() ) {
for ( int i = a.size() - 1; i >= 0; --i ) {
if ( a[i] != b[i] ) return a[i] > b[i];
}
return 0;
}
return a.size() > b.size();
}
void make ( int n, string m )
{
if ( n < 4 ) {
ans = "0";
return ;
}
if ( pd ( m, fib[n - 1] ) ) {
string s1 = sub ( fib[n], "2" );
if ( !pd ( m, s1 ) ) {
ans = sub ( m, fib[n - 2] );
} else {
ans = sub ( m, fib[n - 1] );;
}
return ;
} else make ( n - 1, m );
}
void MOD ( string s, LL k )
{
LL tem = 0;
for ( int i = s.size() - 1; i >= 0; --i ) {
tem = ( tem * 10 + s[i] - '0' ) % k;
}
cout << tem << endl;
}
int main()
{
fib[0] = "0";
fib[1] = "1";
for ( int i = 2; i <= 1000; ++i ) {
fib[i] = add ( fib[i - 1] , fib[i - 2] );
}
cin >> T;
while ( T-- ) {
cin >> n >> m;
reverse ( m.begin(), m.end() );
make ( n, m );
MOD ( ans, 258280327 );
}
}