[规律]JZOJ 4213 对你的爱深不见底

Description

出乎意料的是,幸运E 的小R 居然赢了那个游戏。现在欣喜万分的小R 想要写一张明信片给小Y,但是因为小R 非常羞涩,所以他打算采用一些比较神奇的方式来表达。
他定义了一些字符串,s1 = a,s2 = b,si =s_i-1  +  s_i-2  (i >=3)。同时他定义了一个字符串s 的权值为一个最大的i <|s|满足s 长度为i 的前缀等于长度为i 的后缀。比如字符串aba 的权值就是1,abab 的权值就是2,aaaa 的权值就是3。
现在小R 在明信片上给出了两个数n 和m,他想要告诉小Y 的信息是字符串sn 的前m个字符组成的字符串的权值。你可以帮小Y 计算一下吗?
 

Input

第一行输入一个正整数T 表示数据组数。
对于每组数据,第一行是两个整数n;m。保证1<= m <=|sn|

Output

对于每组数据,输出一个整数表示答案。答案可能很大,你只需要输出模258280327 后的答案。
 

Sample Input

2
4 3
5 5

Sample Output

1
2
 

Data Constraint

对于30% 的数据,n <= 20
对于60% 的数据,n <= 60
对于100% 的数据,n <= 10^3,1 <= T <= 100

分析

SB规律题

我考场发现了错误规律

打了2h+

因为T1T2不可做

设n为最小的满足f[n]>m+1

那么答案为m-f[n-2]

高精

别问我怎么推的,没有人推出来,dalao都说显然

The love to you is deep in s.

 

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const ll P=258280327ll;
const ll G=1e5;
int T,n;
struct LJGJD {
    ll a[1010];
    int len;
    void clear() {
        for (int i=0;i<1010;i++) a[i]=0;len=0;
    }
}m,f[1010];

LJGJD Plus(LJGJD x,LJGJD y) {
    LJGJD a=x,b=y,c;c.clear();
    for (int i=1;i<=max(a.len,b.len);i++) {
        c.a[i]+=a.a[i]+b.a[i];
        c.a[i+1]+=c.a[i]/G;
        c.a[i]%=G;
    }
    c.len=max(a.len,b.len);
    if (c.a[c.len+1]) c.len++;
    return c;
}

LJGJD Sub(LJGJD x,LJGJD y) {
    LJGJD a=x,b=y,c;c.clear();
    for (int i=1;i<=max(a.len,b.len);i++) {
        c.a[i]+=a.a[i]-b.a[i];
        while (c.a[i]<0) c.a[i]+=G,c.a[i+1]--;
    }
    c.len=max(a.len,b.len);
    while (!c.a[c.len]) c.len--;
    return c;
}

bool Bigger(LJGJD x,LJGJD y) {
    if (x.len<y.len) return 0;
    if (x.len>y.len) return 1;
    for (int i=x.len;i;i--)
        if (x.a[i]>y.a[i]) return 1;
        else if (x.a[i]<y.a[i]) return 0;
    return 0;
}

ll Mod(LJGJD x) {
    ll ans=0,g=G%P;
    for (int i=x.len;i;i--) ans=(ans*g+x.a[i]%P)%P;
    return ans;
}

int main() {
    f[1].a[1]=f[2].a[1]=1ll;f[1].len=f[2].len=1;
    for (int i=3;i<=1001;i++) f[i]=Plus(f[i-1],f[i-2]);
    for (scanf("%d",&T);T;T--) {
        char c[10010];
        int len=0;ll k=1ll;
        scanf("%d%s",&n,c+1);len=strlen(c+1);
        m.clear();m.len=1;
        for (int i=len;i;i--) {
            m.a[m.len]+=(c[i]-'0')*k;k*=10ll;
            if (k==G&&i!=1) k=1ll,m.len++;
        }
        if (n==1||n==2||n==3||(m.len==1&&(m.a[1]==1||m.a[1]==2))) {
            printf("0\n");
            continue;
        }
        LJGJD w=m;m=Plus(m,f[1]);
        for (int i=4;i<=n+1;i++)
            if (Bigger(f[i],m)) {
                w=Sub(w,f[i-2]);
                ll ans=Mod(w);
                printf("%lld\n",ans);
                break;
            }
    }
}
View Code

 

posted @ 2019-01-24 21:00  Vagari  阅读(232)  评论(0编辑  收藏  举报