题意
定义一些字符串,
S1=a,S2=b,Si=Si−1+Si−2(i≥3)
。
同时定义一个字符串
S
的权值为一个最大的
求字符串
Sn
的前
m
个字符组成的字符串的权值。
1≤m≤|Sn|
数据组数
T≤100
Time
Limits:1000ms
Memory
Limits:512M
分析
结论:令
n
为最小的
这个结(规)论(律)可以打个表看出来。题解说证明很显然(然而我并没想出来,我还是太蠢啦)。
然后用高精度就行了。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 1005,Mo = 258280327;
struct BigInt
{
int a[505],l;
}Num[MAXN],M;
int A[MAXN];
void Add(BigInt &a,BigInt &b,BigInt &c)
{
for(int i = 1;i < c.l + 1;i ++) c.a[i] = 0;
c.l = 0;
for(int i = 1;i <= max(a.l,b.l);i ++)
{
c.a[i] += a.a[i] + b.a[i];
c.a[i + 1] += c.a[i] / 10;
c.a[i] %= 10;
}
c.l = max(a.l,b.l);
while (c.a[c.l + 1]) c.l ++,c.a[c.l + 1] = c.a[c.l] / 10,c.a[c.l] %= 10;
}
bool Min(BigInt &a,BigInt &b)
{
if (a.l < b.l) return 1;
if (a.l > b.l) return 0;
for(int i = a.l;i;i --)
if (a.a[i] < b.a[i]) return 1; else
if (a.a[i] > b.a[i]) return 0;
return 0;
}
void Work()
{
memset(M.a,0,sizeof M.a);
M.l = 0;
int k;
scanf("%d", &k);
char c;
while (c = getchar(),c < '0' || c > '9');
A[M.l = 1] = c - 48;
while (c = getchar(),c >= '0' && c <= '9') A[++ M.l] = c - 48;
for(int i = M.l;i;i --) M.a[M.l - i + 1] = A[i];
M.a[1] ++;
for(int i = 1;i <= M.l;i ++) M.a[i + 1] += M.a[i] / 10,M.a[i] %= 10;
if (M.a[M.l + 1]) M.l ++;
int l = 1,r = 1001,n;
while (l <= r)
{
int mid = l + r >> 1;
if (Min(M,Num[mid])) n = mid,r = mid - 1; else l = mid + 1;
}
n -= 2;
M.a[1] --;
for(int i = 1;i <= Num[n].l;i ++)
{
M.a[i] -= Num[n].a[i];
if (M.a[i] < 0) M.a[i] += 10,M.a[i + 1] --;
}
while (M.l > 1 && !M.a[M.l]) M.l --;
int p = 0;
for (int i = M.l;i;i --)
p = (p * 10ll + M.a[i]) % Mo;
printf("%d\n", p);
}
int main()
{
int T;
scanf("%d", &T);
Num[1].a[1] = Num[1].l = 1;
Num[2] = Num[1];
for(int i = 3;i <= 1001;i ++) Add(Num[i - 2],Num[i - 1],Num[i]);
for(;T;T --) Work();
}