Luogu P3263 [JLOI2015]有意义的字符串

Link
\(e=\frac{b+\sqrt d}2,i=\frac{b-\sqrt d}2\)
显然\(f_n=e^n+i^n\)是一个整数,且\(f_n=(e+i)f_{n-1}+eif_{n-2}\)
递推式中的\(e+i=b,ei=\frac{b^2-d}4\),根据题目条件这两个也是整数。
因此我们可以利用矩阵快速幂求出\(f_n\bmod P\)
显然\(i\in(-1,0]\),因此\(i^n\in(-1,0]\),因此\(\lfloor e^n\rfloor\equiv f_n-\lceil |i^n|\rceil\pmod P\),直接判断即可。

#include<cstdio>
#include<cstring>
using u64=unsigned long long;
const u64 P=7528443412579576937ll;
u64 inc(u64 a,u64 b){return a+=b,a>=P? a-P:a;}
u64 mul(u64 a,u64 b){u64 r=0;for(;b;b>>=1,a=inc(a,a))if(b&1)r=inc(a,r);return r;}
struct matrix{u64 a[3][3];matrix(){memset(a,0,72);}u64*operator[](int x){return a[x];}}E,I;
matrix operator*(matrix a,matrix b)
{
    matrix c;
    for(int i=1;i<=2;++i) for(int j=1;j<=2;++j) for(int k=1;k<=2;++k) c[i][j]=inc(c[i][j],mul(a[i][k],b[k][j]));
    return c;
}
int main()
{
    u64 b,d,n;int f;
    scanf("%llu%llu%llu",&b,&d,&n);
    if(!n) return !printf("1");
    f=--n&1,E[1][2]=(d-b*b)/4,E[2][1]=1,E[2][2]=b,I[1][1]=I[2][2]=1;
    for(;n;n>>=1,E=E*E) if(n&1) I=E*I;
    printf("%llu",inc(mul(2,I[1][2]),mul(b,I[2][2]))-(d*d^b&&f));
}
posted @ 2020-02-27 22:38  Shiina_Mashiro  阅读(74)  评论(0编辑  收藏  举报